29

私は通常、HTML5 PostMessage APIを使用して、iframe コンテンツから親フレームに情報を伝達します。最近、コンテンツを Android WebView 内で使用しました (私が知る限り、これは iframe に相当するネイティブ Android です)。ネイティブ アプリが送信した PostMessage イベントをリッスンする方法はありますか?

私はaddJavascriptInterfaceが存在することを認識しています。新しいものを書かずに既存の PostMessage コードを再利用する方法があることを願っています。

4

5 に答える 5

11

この質問は古いと思いますが、出くわしたので、ここで答えると思いました。要するに、postMessage は、少なくとも子 iframe から親ウィンドウへの通信では機能することがわかりましたが、...

AndroidのWebViewでのiframeの動作が本当に気に入らなかったことが判明したため、代わりにiframeのコンテンツを直接レンダリングしました(提案どおり)。これにより、2 つの問題が発生しました。1 つ目は、その iframe からその親へのメッセージング フックが多数あったこと、2 つ目は、これらのイベントに対応するために Android を呼び出す必要があったことです。

これは、iframe 全体に散りばめられたコードからのメッセージの例です。

    parent.postMessage(JSON.stringify({
        action    : 'openModal',
        source    : embedId
    }), '*');

Android を使用している場合、WebView での実行時にこのリクエストを処理するオブジェクトを挿入するために、Android の javascript インターフェイスのサポートを使用する必要があります。

Android 側では、これは次のようになります。

class JsObject {
   @JavascriptInterface
    public boolean postMessage(String json, String transferList) {
        return false; // here we return true if we handled the post.
    }
}

// And when initializing the webview... 
webView.addJavascriptInterface(new JsObject(), "totDevice");

このWebView内でtotDevice実行すると存在し、iframeで実行すると存在しません。これで、ラッパーを作成してこの状態をチェックし、直接呼び出すのではなく、2 つのメソッドをきれいに切り替えることができますparent.postMessage。ここでは、一部のメッセージのみを処理したい場合に備えて、Android 実装にブール値スイッチも追加しました。

function postMessage(parent, json, transferlist) {
    if (!totDevice || !totDevice.postMessage(json, transferList)) {
        parent.postMessage(json, transferlist);
    }
}

上記の元の投稿メッセージは次のように書き換えることができます。

    postMessage(parent, JSON.stringify({
        action    : 'openModal',
        source    : embedId
    }), '*');

これで、(少なくともコードのこの部分を) 変更せずに iframe または android WebView で実行できる単一のコード セットができました。

それが誰かを助けることを願っています。

于 2016-10-05T17:03:15.837 に答える
3

ここでの回答は、投稿された時点では適切な回答ですが、androidx.webkit が利用可能になったので、それが推奨されるアプローチだと思います。

特に、WebViewCompat.addWebMessageListenerjavascript WebViewCompat.postWebMessagePostMessage API に相当するものです。

ドキュメントからコピーしたコード例を次に示します。

 // Web page (in JavaScript)
 myObject.onmessage = function(event) {
   // prints "Got it!" when we receive the app's response.
   console.log(event.data);
 }
 myObject.postMessage("I'm ready!");
 
 // App (in Java)
 WebMessageListener myListener = new WebMessageListener() {
   @Override
   public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
            boolean isMainFrame, JavaScriptReplyProxy replyProxy) {
     // do something about view, message, sourceOrigin and isMainFrame.
     replyProxy.postMessage("Got it!");
   }
 };
 if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
   WebViewCompat.addWebMessageListener(webView, "myObject", rules, myListener);
 }
于 2021-09-08T22:38:47.737 に答える