web-dev-qa-db-ja.com

React-native Android WebViewハンドルがロード前にURLをクリックした

反応ネイティブでWebViewを介してWebサイトを表示しています。このWebサイトには、PassWallet(.pkpass)ファイルへのリンクがあります(唯一の使用例ではありません)。このWebサイトのリンクをクリックしたときに、他のWebサイトなのか、.pkpassファイルなのかを確認したいと思います。このチェックの実行中は何もロードしたくありません。関数が終了するまで待ってください。Webサイトを開くか、別のアプリを開くかなどがわかります。私のルーティング関数全体があり、私の意見ではこの場合のために反応ネイティブが構築されたので、これを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)を取得し、ロードしようとしているURLを確認できます。 e.navigationTypeを使用して、それがクリックかどうかを確認することもできます。

Androidこの関数は存在しません。ネイティブ側には関数shouldOverrideUrlLoadingがありますが、この関数はreact-nativeに実装されていません。次のGitHubの問題が見つかりました/ PR https://github.com/facebook/react-native/pull/6478 おそらく、この問題は解決されており、説明もあるため、この関数は実装されていません。

それで私は自分で道を見つけ始めました。 WebViewを表示するネイティブUIコンポーネントを作成し、このメソッドを実装しました。

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でtrueまたはfalseを設定してshouldOverrideUrlLoading関数を制御する方法を教えてください。そして、私自身の機能を利用可能にする可能性はありますか?今までは、なんとかonChangeイベントをトリガーするだけでしたか?

IOSで作ったのと同じにしたいだけです。たぶん誰かが現れて、これは何らかの理由で不可能であると私に言いますが、どのように私はこのようにケースを処理する必要がありますか? URLスキーマがあることは知っていますが、この場合は機能しないことを知っています。

9
vanBrunneren

反応ネイティブでWebViewを介してWebサイトを表示しています。このWebサイトには、PassWallet(.pkpass)ファイルへのリンクがあります(唯一の使用例ではありません)。このWebサイトのリンクをクリックしたときに、他のWebサイトなのか、.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#stoploadinghttps://github.com/facebook/react-native/pull/6886

9
maha_funk

onShouldStartLoadWithRequestは2018年末から react-native-community/react-native-webview バージョン。 PRを参照

1
Jules Randolph