无法在两个 WebView 之间进行通信

Unable to communicate between two WebViews

为了解释我想要实现的目标,我写下了我能够做的事情,然后 - 当出现问题时。什么效果好:

1) 我有 webView1 包含在加载的 HTML

<button onclick="android.buttonPressed();">Click</button>

绑定接口:

private class WebAppInterface1 {
    Context context;

    WebAppInterface1(Context c) {
        context = c;
    }

    @JavascriptInterface
    public void buttonPressed() {
        Toast.makeText(context, "buttonPressed", Toast.LENGTH_LONG).show();
    }
}

HTML 按钮有效。

2) 我有 webView2 包含在加载的 HTML

<script>
    function f() {
        document.write("bla bla bla");
    }
</script>

那我打电话给

webView2.loadUrl("javascript:f();");

在 android 代码中,它也可以工作。


现在我想通过按 webView1 中的按钮修改 webView2 的页面。从技术上讲,这意味着当 JS 界面检测到 webView1 中的点击时,我想在 webView2 中调用 f()。所以我添加了这一行

webView2.loadUrl("javascript:f();");

in buttonPressed() JS 接口中的函数。但它没有效果。什么会导致问题?连接这些接收方和发送方是否有任何限制?也许我错过了一些设置或权限?

这是我的项目文件,我尽量使它们尽可能简单:layout, html, java。没有编辑其他文件。如果需要,可以提供任何其他信息。

我知道我的问题与另一个问题有关:无法从非主线程更新UI(在 SO here and here).但就我而言,由于某种原因没有任何错误。可能是因为 Java脚本不像 Java 那样 "strict"。

所以通过在我的 activity class 中添加 android.os.Handler,在 onCreate 函数中分配它来解决:

handler = new Handler() {
    public void handleMessage(Message msg) {
        webView2.loadUrl("javascript:f()");
    }
}

并在 buttonPressed 函数中访问它:

handler.obtainMessage(1).sendToTarget();

P.S。另一种方法是通过 Runnable 和调用 runOnUiThread(runnable) 来包装调用 webView2.loadUrl("javascript:f()");。它看起来更整洁:

webView1.addJavascriptInterface(new Object() {
    @JavascriptInterface
    public void buttonPressed() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                webView2.loadUrl("javascript:f()");
            }
        });
    }
}, "android");

P.P.S。 Enabling Java 8 in app/build.gradle 允许写得更整洁:

runOnUiThread(()->{webView2.loadUrl("javascript:f()");});