Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enables communication between the webview and RN #7020

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Libraries/Components/WebView/WebView.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,21 @@ var WebView = React.createClass({
*/
domStorageEnabled: PropTypes.bool,

/**
* A callback that will be executed once the webview
* sends a message to RN.
* @platform android
*/
onMessage: PropTypes.func,

/**
* A protocol that the webview can use to communicate with RN.
* When the WebView triggers requests to myProtocol://something
* the 'onMessage' callback passed to the webview will be called.
* @platform android
*/
messageProtocol: PropTypes.string,

/**
* Sets the JS to be injected when the webpage loads.
*/
Expand Down Expand Up @@ -226,6 +241,8 @@ var WebView = React.createClass({
contentInset={this.props.contentInset}
automaticallyAdjustContentInsets={this.props.automaticallyAdjustContentInsets}
onLoadingStart={this.onLoadingStart}
onMessage={this.props.onMessage}
messageProtocol={this.props.messageProtocol}
onLoadingFinish={this.onLoadingFinish}
onLoadingError={this.onLoadingError}
testID={this.props.testID}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;

import com.facebook.react.views.webview.events.MessageEvent;
import com.facebook.react.views.webview.events.TopLoadingErrorEvent;
import com.facebook.react.views.webview.events.TopLoadingFinishEvent;
import com.facebook.react.views.webview.events.TopLoadingStartEvent;
Expand Down Expand Up @@ -87,6 +90,21 @@ private static class ReactWebViewClient extends WebViewClient {

private boolean mLastLoadFailed = false;

@Override
public WebResourceResponse shouldInterceptRequest (final WebView webView, WebResourceRequest request) {
ReactWebView reactWebView = (ReactWebView) webView;

if (reactWebView.getMessageProtocol().equals(request.getUrl().getScheme())) {
WritableMap eventData = Arguments.createMap();
eventData.putString("url", request.getUrl().toString());
eventData.putString("method", request.getMethod().toString());

dispatchEvent(webView, new MessageEvent(webView.getId(), SystemClock.nanoTime(), eventData));
}

return super.shouldInterceptRequest(webView, request);
}

@Override
public void onPageFinished(WebView webView, String url) {
super.onPageFinished(webView, url);
Expand Down Expand Up @@ -181,6 +199,7 @@ private WritableMap createWebViewEvent(WebView webView, String url) {
*/
private static class ReactWebView extends WebView implements LifecycleEventListener {
private @Nullable String injectedJS;
private @Nullable String messageProtocol;

/**
* WebView must be created with an context of the current activity
Expand Down Expand Up @@ -212,6 +231,14 @@ public void setInjectedJavaScript(@Nullable String js) {
injectedJS = js;
}

public String getMessageProtocol() {
return messageProtocol;
}

public void setMessageProtocol(@Nullable String mp) {
messageProtocol = mp;
}

public void callInjectedJavaScript() {
if (getSettings().getJavaScriptEnabled() &&
injectedJS != null &&
Expand Down Expand Up @@ -271,7 +298,6 @@ public void setDomStorageEnabled(WebView view, boolean enabled) {
view.getSettings().setDomStorageEnabled(enabled);
}


@ReactProp(name = "userAgent")
public void setUserAgent(WebView view, @Nullable String userAgent) {
if (userAgent != null) {
Expand All @@ -290,6 +316,11 @@ public void setInjectedJavaScript(WebView view, @Nullable String injectedJavaScr
((ReactWebView) view).setInjectedJavaScript(injectedJavaScript);
}

@ReactProp(name = "messageProtocol")
public void setMessageProtocol(WebView view, @Nullable String messageProtocol) {
((ReactWebView) view).setMessageProtocol(messageProtocol);
}

@ReactProp(name = "source")
public void setSource(WebView view, @Nullable ReadableMap source) {
if (source != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

package com.facebook.react.views.webview.events;

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

/**
* Event emitted when there is an error in loading.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this Javadoc correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, sorry -- copypasta :)

*/
public class MessageEvent extends Event<MessageEvent> {

public static final String EVENT_NAME = "message";
private WritableMap mEventData;

public MessageEvent(int viewId, long timestampMs, WritableMap eventData) {
super(viewId, timestampMs);
mEventData = eventData;
}

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

@Override
public boolean canCoalesce() {
return false;
}

@Override
public short getCoalescingKey() {
// All events for a given view can be coalesced.
return 0;
}

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