React-native android WebView句柄在加载

时间:2016-08-17 14:30:40

标签: javascript android reactjs webview react-native

我通过反复原生的WebView显示网站。在本网站上有一个PassWallet(.pkpass)文件的链接(不是唯一的用例)。当我点击本网站上的任何链接时,我想检查它是否是其他网站或.pkpass文件或其他什么。当这个检查正在运行时,我不想加载任何东西,只要等到我的功能完成,我就知道我是应该打开一个网站还是打开另一个应用程序或其他什么。我想在JavaScript方面做这个,因为我的整个路由功能都在那里,在我看来本机是为这种情况而构建的: - )

在iOS上有这个美丽的功能onShouldStartLoadWithRequest,它完全符合我的需要。

_onShouldStartLoadWithRequest(e) {

    if(checkUrl(e.url)) {

        let Router = this.props.navigator.props.router;
        let route = Router.getRouteFromUrl(e.url);
        this.props.navigator.push(route);

        return false;

    }

    return true;
}  

我收到了事件(e)并且可以查看它尝试加载的网址。我甚至可以用e.navigationType检查它是否是点击或其他什么。

现在在Android上这个功能不存在。在本机端有函数shouldOverrideUrlLoading但是这个函数没有在react-native中实现。 我发现了以下GitHub问题/ PR https://github.com/facebook/react-native/pull/6478 我想现在,因为这个问题已经结束,因此有解释,这个功能没有实现。

所以我开始自己找到一种方法。我创建了一个Native UI Component,它显示了一个WebView,然后实现了这个方法。

CustomWebViewManager.java:

package ch.mypackage;

import android.support.annotation.Nullable;
import android.webkit.WebView;

import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;

public class CustomWebViewManager extends SimpleViewManager<CplusWebView> {

    @Override
    public String getName() {
        return "CplusWebView";
    }

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

    @ReactProp(name = "url")
    public void setUrl(CustomWebView view, @Nullable String url) {
        view.loadUrl(url);
    }

    @ReactProp(name = "javascriptEnabled")
    public void setJavascriptEnabled(CustomWebView view, boolean enabled) {
        view.getSettings().setJavaScriptEnabled(enabled);
    }

}

CustomWebView.java

package ch.couponplus;

import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;

public class CustomWebView extends WebView {

    EventDispatcher eventDispatcher;
    EventWebClient eventWebClient;

    public CustomWebView(ThemedReactContext reactContext) {
        super(reactContext);
        eventWebClient = new EventWebClient();
        setWebViewClient(eventWebClient);
    }

    protected class EventWebClient extends WebViewClient {

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {

            WritableMap event = Arguments.createMap();
            event.putString("message", "MyMessage");
            ReactContext reactContext = (ReactContext)getContext();
            reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                    getId(),
                    "topChange",
                    event);

            return true;
        }

    }

}

它按预期工作。我现在可以在JS中触发shouldOverrideUrlLoading函数并生成日志或其他内容。

但我的问题是我现在如何在Javascript中设置truefalse来控制我的shouldOverrideUrlLoading功能?是否有可能使我自己的功能可用?直到现在我才设法触发onChange事件?

我只想和我在iOS中做的一样。也许有人出现并告诉我,无论出于何种原因这是不可能的,但我应该如何或如何处理这样的案件?我知道有Url架构,但我知道他们在这种情况下不会工作。

2 个答案:

答案 0 :(得分:8)

  

我正在通过反应原生的WebView展示一个网站。就这个   网站上有一个PassWallet(.pkpass)文件的链接(不是唯一的   用例)。当我点击本网站上的任何链接时,我想查看   无论是其他网站还是.pkpass文件或其他任何内容。

我也有类似的问题,我想检查在我的react-native应用程序的webView中点击的链接类型。就像你说的那样,在iOS端的功能onShouldStartLoadWithRequest,在Android端不存在。

这是我在Android方面的解决方案。

   <WebView
        source={{uri: this.props.url}}
        onLoad={this.onLoad.bind(this)}
        onShouldStartLoadWithRequest={this._onShouldStartLoadWithRequest}
        onNavigationStateChange = {this._onShouldStartLoadWithRequest} 
    />

然后你可以这样做:

  _onShouldStartLoadWithRequest(e) {

if(checkUrl(e.url)) {

    let Router = this.props.navigator.props.router;
    let route = Router.getRouteFromUrl(e.url);
    this.props.navigator.push(route);

    this.refs[WEBVIEW_REF].stopLoading();  // <---- Add a similar line
    //This will tell your webView to stop processing the clicked link

    return false;

}

return true;

如果我正确理解您的问题,您需要一种方法来检查在WebView中单击的URL,然后根据URL决定继续或停止并执行其他操作。我在我们的应用程序中处理它的方式上面的解决方案。

查看以下链接:

https://facebook.github.io/react-native/docs/webview.html#stoploading https://github.com/facebook/react-native/pull/6886

答案 1 :(得分:0)

自2018年底以来,已在react-native-community/react-native-webview版本中支持

onShouldStartLoadWithRequestSee PR