From a5ccd4378aa8776e8e38bf2335818a9af2f9cf1e Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Mon, 8 May 2017 12:19:51 +0300 Subject: [PATCH] request geolocation permissions --- .../WebViewBridgeManager.java | 74 ++++++++++++++++--- .../WebViewBridgePackage.java | 2 +- webview-bridge/index.android.js | 8 ++ 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgeManager.java b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgeManager.java index 49484906..de18682a 100644 --- a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgeManager.java +++ b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgeManager.java @@ -44,10 +44,16 @@ import java.net.MalformedURLException; import javax.annotation.Nullable; + import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.views.webview.WebViewConfig; import android.webkit.ValueCallback; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.modules.core.DeviceEventManagerModule; +import org.json.JSONObject; +import org.json.JSONException; + public class WebViewBridgeManager extends ReactWebViewManager { private static final String REACT_CLASS = "RCTWebViewBridge"; private static final String HTML_ENCODING = "UTF-8"; @@ -58,12 +64,15 @@ public class WebViewBridgeManager extends ReactWebViewManager { public static final int COMMAND_SEND_TO_BRIDGE = 101; public static final int RESET_OK_HTTP_CLIENT = 102; + public static final int GEO_PERMISSIONS_GRANTED = 103; private static final String BLANK_URL = "about:blank"; private WebViewConfig mWebViewConfig; + private static ReactApplicationContext reactNativeContext; - public WebViewBridgeManager() { + public WebViewBridgeManager(ReactApplicationContext context) { + this.reactNativeContext = context; mWebViewConfig = new WebViewConfig() { public void configWebView(WebView webView) { } @@ -80,38 +89,61 @@ public String getName() { } @Override - public @Nullable Map getCommandsMap() { + public @Nullable + Map getCommandsMap() { Map commandsMap = super.getCommandsMap(); commandsMap.put("sendToBridge", COMMAND_SEND_TO_BRIDGE); commandsMap.put("resetOkHttpClient", RESET_OK_HTTP_CLIENT); + commandsMap.put("geoPermissionsGranted", GEO_PERMISSIONS_GRANTED); return commandsMap; } protected static class ReactWebChromeClient extends WebChromeClient { + String origin; + GeolocationPermissions.Callback callback; + public void onProgressChanged(WebView view, int newProgress) { if (newProgress < 80) { ((ReactWebView) view).callInjectedOnStartLoadingJavaScript(); } } + + @Override + public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { + try { + WritableMap params = Arguments.createMap(); + JSONObject event = new JSONObject(); + event.put("type", "request_geo_permissions"); + params.putString("jsonEvent", event.toString()); + reactNativeContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit("gethEvent", params); + this.callback = callback; + this.origin = origin; + } catch (JSONException e) { + + } + } + + public void geoCallback() { + if (callback != null) { + callback.invoke(origin, true, false); + } + } } @Override protected WebView createViewInstance(ThemedReactContext reactContext) { ReactWebView webView = new ReactWebView(reactContext); - webView.setWebChromeClient(new WebChromeClient() { - @Override - public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { - callback.invoke(origin, true, false); - } - }); reactContext.addLifecycleEventListener(webView); mWebViewConfig.configWebView(webView); webView.getSettings().setBuiltInZoomControls(true); webView.getSettings().setDisplayZoomControls(false); webView.getSettings().setUseWideViewPort(true); + webView.getSettings().setUseWideViewPort(true); + webView.getSettings().setGeolocationEnabled(true); webView.setInitialScale(1); // Fixes broken full-screen modals/galleries due to body height being 0. @@ -123,7 +155,8 @@ public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermiss WebView.setWebContentsDebuggingEnabled(true); } - webView.setWebChromeClient(new ReactWebChromeClient()); + ReactWebChromeClient client = new ReactWebChromeClient(); + webView.setWebChromeClient(client); webView.addJavascriptInterface(new JavascriptBridge(webView), "WebViewBridge"); StatusBridge bridge = new StatusBridge(reactContext, webView); webView.addJavascriptInterface(bridge, "StatusBridge"); @@ -143,6 +176,10 @@ public void receiveCommand(WebView root, int commandId, @Nullable ReadableArray case RESET_OK_HTTP_CLIENT: ((ReactWebView) root).getStatusBridge().resetCleint(); break; + + case GEO_PERMISSIONS_GRANTED: + ((ReactWebChromeClient) ((ReactWebView) root).getWebChromeClient()).geoCallback(); + break; default: //do nothing!!!! } @@ -206,8 +243,10 @@ protected void addEventEmitters(ThemedReactContext reactContext, WebView view) { } private static class ReactWebView extends WebView implements LifecycleEventListener { - private @Nullable String injectedJS; - private @Nullable String injectedOnStartLoadingJS; + private @Nullable + String injectedJS; + private @Nullable + String injectedOnStartLoadingJS; private StatusBridge bridge; private boolean messagingEnabled = false; @@ -229,7 +268,6 @@ public void postMessage(String message) { * * Activity Context is required for creation of dialogs internally by WebView * Reactive Native needed for access to ReactNative internal system functionality - * */ public ReactWebView(ThemedReactContext reactContext) { super(reactContext); @@ -330,6 +368,18 @@ public void setStatusBridge(StatusBridge bridge) { this.bridge = bridge; } + private ReactWebChromeClient chromeClient; + + @Override + public void setWebChromeClient(WebChromeClient client) { + super.setWebChromeClient(client); + chromeClient = (ReactWebChromeClient) client; + } + + public ReactWebChromeClient getWebChromeClient() { + return this.chromeClient; + } + public StatusBridge getStatusBridge() { return this.bridge; } diff --git a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgePackage.java b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgePackage.java index 1e189c4d..de48b193 100644 --- a/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgePackage.java +++ b/android/src/main/java/com/github/alinz/reactnativewebviewbridge/WebViewBridgePackage.java @@ -19,7 +19,7 @@ public List createNativeModules(ReactApplicationContext reactAppli @Override public List createViewManagers(ReactApplicationContext reactApplicationContext) { return Arrays.asList( - new WebViewBridgeManager() + new WebViewBridgeManager(reactApplicationContext) ); } diff --git a/webview-bridge/index.android.js b/webview-bridge/index.android.js index b25914f6..b51ab410 100644 --- a/webview-bridge/index.android.js +++ b/webview-bridge/index.android.js @@ -188,6 +188,14 @@ var WebViewBridge = React.createClass({ ); }, + geoPermissionsGranted: function () { + UIManager.dispatchViewManagerCommand( + this.getWebViewBridgeHandle(), + UIManager.RCTWebViewBridge.Commands.geoPermissionsGranted, + [] + ); + }, + /** * We return an event with a bunch of fields including: * url, title, loading, canGoBack, canGoForward