Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
shexiaoheng committed Dec 21, 2015
1 parent b4d9874 commit 2a2f1c9
Show file tree
Hide file tree
Showing 10 changed files with 411 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/build
proguard-rules.pro
webview.iml
.DS_Store
.DS_Store

Binary file added Screenshot/result_one.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 23
buildToolsVersion "23.0.2"

defaultConfig {
minSdkVersion 16
targetSdkVersion 23
}
}

dependencies {
compile 'com.facebook.react:react-native:0.17.0'
}
65 changes: 65 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
var React = require('react-native');

var { requireNativeComponent,PropTypes,NativeModules,View } = React;

var UIManager = NativeModules.UIManager;

var WEBVIEW_REF = 'webview';

var WebView = React.createClass({
propTypes: {
...View.propTypes,
automaticallyAdjustContentInsets: PropTypes.bool,
contentInset: PropTypes.object,
html: PropTypes.string,
injectedJavaScript: PropTypes.string,
onNavigationStateChange: PropTypes.func,
renderError: PropTypes.func,
renderLoading: PropTypes.func,
startInLoadingState: PropTypes.bool,
url: PropTypes.string,
javaScriptEnabledAndroid: PropTypes.bool,
},
_onNavigationStateChange: function(event){
if(this.props.onNavigationStateChange){
this.props.onNavigationStateChange(event.nativeEvent);
}
},
_getWebViewHandle: function(){
return React.findNodeHandle(this.refs[WEBVIEW_REF]);
},
goBack: function(){
UIManager.dispatchViewManagerCommand(
_getWebViewHandle,
UIManager.RCTWebView.Commands.goBack,
null,
);
},
goForward: function(){
UIManager.dispatchViewManagerCommand(
_getWebViewHandle,
UIManager.RCTWebView.Commands.goForward,
null,
);
},
reload: function(){
UIManager.dispatchViewManagerCommand(
_getWebViewHandle,
UIManager.RCTWebView.Commands.reload,
null,
);
},
render(){
return(
<NativeWebView
ref={WEBVIEW_REF}
{...this.props}
onNavigationStateChange={this._onNavigationStateChange}
/>
);
}
});

var NativeWebView = requireNativeComponent('RCTWebView',WebView);

module.exports = WebView;
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "react-native-webview",
"version": "1.0.8",
"description": "andorid webview for react-native",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/beefe/react-native-webview.git"
},
"keywords": [
"react-native-webview"
],
"author": "shexiaoheng",
"license": "MIT",
"bugs": {
"url": "https://github.com/beefe/react-native-webview/issues"
},
"homepage": "https://github.com/beefe/react-native-webview#readme"
}
4 changes: 4 additions & 0 deletions src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.heng.webview">

</manifest>
51 changes: 51 additions & 0 deletions src/main/java/com/heng/webview/NavigationStateChangeEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.heng.webview;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;

/**
* Created by heng on 15/12/14.
*/
public class NavigationStateChangeEvent extends Event<NavigationStateChangeEvent> {

public static final String EVENT_NAME = "navigationStateChange";

private final boolean canGoBack;
private final boolean canGoForward;
private final String url;
private final String title;
private final boolean loading;

protected NavigationStateChangeEvent(int viewTag,long timestampMs,boolean canGoBack,boolean canGoForward,
String url,String title,boolean loading){
super(viewTag,timestampMs);
this.canGoBack = canGoBack;
this.canGoForward = canGoForward;
this.url = url;
this.title = title;
this.loading = loading;
}

@Override
public String getEventName() {
return EVENT_NAME;
}

@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
rctEventEmitter.receiveEvent(getViewTag(),getEventName(),serializeEventData());
}

private WritableMap serializeEventData() {
WritableMap eventData = Arguments.createMap();
eventData.putBoolean("canGoBack", canGoBack);
eventData.putBoolean("canGoForward", canGoForward);
eventData.putString("url", url);
eventData.putString("title", title);
eventData.putBoolean("loading", loading);
return eventData;
}

}
85 changes: 85 additions & 0 deletions src/main/java/com/heng/webview/ReactWebView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.heng.webview;

import android.graphics.Bitmap;
import android.os.Build;
import android.os.SystemClock;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.EventDispatcher;

/**
*/
public class ReactWebView extends WebView {

EventDispatcher eventDispatcher;
EventWebClient eventWebClient;

protected class CustomWebChromeClient extends WebChromeClient {
@Override
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
}

protected class EventWebClient extends WebViewClient {

String injectedJavaScript;

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}

public void setInjectedJavaScript(String injectedJavaScript) {
this.injectedJavaScript = injectedJavaScript;
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
eventDispatcher.dispatchEvent(new NavigationStateChangeEvent(
getId(), SystemClock.uptimeMillis(), view.canGoBack(), view.canGoForward(),
url, view.getTitle(), true));
}

@Override
public void onPageFinished(WebView view, String url) {
eventDispatcher.dispatchEvent(new NavigationStateChangeEvent(
getId(), SystemClock.uptimeMillis(),false, view.canGoForward(),
url, view.getTitle(), true));
if(this.injectedJavaScript != null) {
view.loadUrl("javascript:(function() { " + injectedJavaScript + "})()");
}
}
}

public ReactWebView(ReactContext reactContext) {
super(reactContext);
eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
eventWebClient = new EventWebClient();
getSettings().setJavaScriptEnabled(true);
getSettings().setBuiltInZoomControls(false);
getSettings().setGeolocationEnabled(false);
getSettings().setAllowFileAccess(true);
getSettings().setAllowFileAccessFromFileURLs(true);
getSettings().setLoadsImagesAutomatically(true);
getSettings().setBlockNetworkImage(false);
getSettings().setBlockNetworkLoads(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
setWebViewClient(eventWebClient);
setWebChromeClient(new CustomWebChromeClient());
}

public void setInjectedJavaScript(String injectedJavaScript) {
eventWebClient.setInjectedJavaScript(injectedJavaScript);
}

}
133 changes: 133 additions & 0 deletions src/main/java/com/heng/webview/WebViewManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.heng.webview;

import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ReactProp;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;

import java.util.Map;

import javax.annotation.Nullable;

/**
*/
public class WebViewManager extends SimpleViewManager<ReactWebView> {

public static final String REACT_CLASS = "RCTWebView";

public static final String AUTOMATICALLY_ADJUST_CONTENT_INSETS = "automaticallyAdjustContentInsets";
public static final String CONTENT_INSET = "contentInset";
public static final String HTML = "html";
public static final String INJECTED_JAVA_SCRIPT = "injectedJavaScript";
public static final String ON_NAVIGATION_STATE_CHANGE = "onNavigationStateChange";
public static final String RENDER_ERROR = "renderError";
public static final String RENDER_LOADING = "renderLoading";
public static final String START_IN_LOADING_STATE = "startInLoadingState";
public static final String URL = "url";
public static final String JAVA_SCRIPT_ENABLE_ANDROID = "javaScriptEnabledAndroid";

public static final int COMMAND_GO_BACK = 1;
public static final int COMMAND_GO_FORWARD = 2;
public static final int COMMAND_RELOAD = 3;

@Override
public String getName() {
return REACT_CLASS;
}

@Override
protected ReactWebView createViewInstance(ThemedReactContext reactContext) {
return new ReactWebView(reactContext);
}

@ReactProp(name = AUTOMATICALLY_ADJUST_CONTENT_INSETS,defaultBoolean = true)
public void setAutomaticallyAdjustContentInsets(ReactWebView view, boolean automaticallyAdjustContentInsets) {
view.getSettings().setLoadsImagesAutomatically(automaticallyAdjustContentInsets);
}


@ReactProp(name = CONTENT_INSET)
public void setContentInset(ReactWebView view,ReadableMap map){
int top = map.getInt("top");
int left = map.getInt("left");
int bottom = map.getInt("bottom");
int right = map.getInt("right");
view.setPadding(left, top, right, bottom);
}

@ReactProp(name = HTML)
public void setHtml(ReactWebView view, String html) {
view.loadData(html, "text/html", "UTF-8");
}

@ReactProp(name = INJECTED_JAVA_SCRIPT)
public void setInjectedJavaScript(ReactWebView view, String injectedJavaScript){
view.setInjectedJavaScript(injectedJavaScript);
}

@ReactProp(name = RENDER_ERROR)
public void setRenderError(ReactWebView view,boolean renderError){
// Unrealized
}

@ReactProp(name = RENDER_LOADING)
public void setRenderLoading(ReactWebView view,boolean renderLoading){
// Unrealized
}

@ReactProp(name = START_IN_LOADING_STATE)
public void setStartInLoadingState(ReactWebView view,boolean startInLoadingState){
// Unrealized
}

@ReactProp(name = URL)
public void setUrl(ReactWebView view, String url) {
view.loadUrl(url);
}

@ReactProp(name = JAVA_SCRIPT_ENABLE_ANDROID)
public void setJavaScriptEnableAndroid(ReactWebView view, boolean javaScriptEnableAndroid) {
view.getSettings().setJavaScriptEnabled(javaScriptEnableAndroid);
}

@Nullable
@Override
public Map<String, Integer> getCommandsMap() {
return MapBuilder.of(
"goBack", COMMAND_GO_BACK,
"goForward", COMMAND_GO_FORWARD,
"reload", COMMAND_RELOAD
);
}

@Override
public void receiveCommand(ReactWebView root, int commandId, ReadableArray args) {
switch (commandId) {
case COMMAND_GO_BACK:
root.goBack();
break;
case COMMAND_GO_FORWARD:
root.goForward();
break;
case COMMAND_RELOAD:
root.reload();
break;
default:
throw new IllegalArgumentException(String.format(
"Unsupported command %d received by %s.",
commandId,
getClass().getSimpleName()));

}
}

@Nullable
@Override
public Map getExportedCustomDirectEventTypeConstants() {
return MapBuilder.of(
NavigationStateChangeEvent.EVENT_NAME, MapBuilder.of("registrationName", ON_NAVIGATION_STATE_CHANGE)
);
}
}
Loading

0 comments on commit 2a2f1c9

Please sign in to comment.