如果在 WebChromeClient#onCreateWindow 的回调中创建了 webview,则 Android WebView addJavascriptInterface 不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21749425/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:01:17  来源:igfitidea点击:

Android WebView addJavascriptInterface does not work if the webview is created in the callback of WebChromeClient#onCreateWindow

androidwebview

提问by zhang

The following is my test code. My problem is that in the page two I can not reference AndroidFunction2. I'm testing this on Nexus 7 with Android 4.4. But it's OK on sumsang i9100 with Android 4.0. Am I doing something wrong, or there is an Android's bug?

以下是我的测试代码。我的问题是在第二页中我无法引用AndroidFunction2。我正在使用 Android 4.4 的 Nexus 7 上对此进行测试。但在搭载 Android 4.0 的 sumsang i9100 上没问题。是我做错了什么,还是安卓的bug?

MainActivity

主要活动

public class MainActivity extends Activity {
    WebView mWebView1;
    WebView mWebView2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final FrameLayout mainFrame = (FrameLayout) this.findViewById(R.id.mainFrame);

        mWebView1 = new WebView(this);
        mWebView1.getSettings().setJavaScriptEnabled(true);
        mWebView1.getSettings().setSupportMultipleWindows(true);
        mWebView1.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return false;
            }
        });
        mWebView1.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onCreateWindow(WebView view, boolean isDialog,
                    boolean isUserGesture, Message resultMsg) {
                mWebView2 = new WebView(MainActivity.this);
                mWebView2.getSettings().setJavaScriptEnabled(true);
                mWebView2.getSettings().setSupportMultipleWindows(true);
                mWebView2.setWebChromeClient(new WebChromeClient() {
                    @Override
                    public void onConsoleMessage(String message, int lineNumber, String sourceID) {
                        Log.d("WebView", "Line: " + lineNumber + ", " + message);
                    }
                });
                mWebView2.addJavascriptInterface(new Object() {
                    @JavascriptInterface
                    public void hello2() {
                    }
                }, "AndroidFunction2");

                (( WebViewTransport )resultMsg.obj).setWebView(mWebView2);
                resultMsg.sendToTarget();
                mainFrame.addView(mWebView2);
                return true;
            }
        });
        mWebView1.addJavascriptInterface(new Object() {
            @JavascriptInterface
            public void hello1() {
            }
        }, "AndroidFunction1");
        mWebView1.loadUrl("file:///sdcard/test_1.html");

        mainFrame.addView(mWebView1);
    }
}

And the two web page,

还有这两个网页,

test_1.html:

test_1.html:

<html>
<body>
    <a href="test_2.html" target="_blank">goto test 2</a>
    <div><a href="javascript:alert(typeof AndroidFunction1);"> alert(typeof AndroidFunction1);</a> </div>
    <div><a href="javascript:alert(typeof window.AndroidFunction1);"> alert(typeof window.AndroidFunction1);</a> </div>
</body>
</html>

test_2.html

test_2.html

<html>
<body>
    <div><a href="javascript:alert(AndroidFunction2);"> alert(AndroidFunction2);</a> </div>
    <div><a href="javascript:alert(typeof window.AndroidFunction2);"> alert(typeof window.AndroidFunction2);</a> </div>
</body>
</html>

回答by Ram Patra

Even I had the same problem and after going through the docs again I found that if you've set your targetSdkVersionto 17 or higher, you must add the @JavascriptInterfaceannotation to any method that you want available to your JavaScript (the method must also be public).

即使我遇到了同样的问题,在再次浏览文档后,我发现如果您将 设置targetSdkVersion17 or higher,则必须将@JavascriptInterface注释添加到您希望 JavaScript 可用的任何方法中(该方法也必须是公共的)。

If you do not provide the annotation, the method is not accessible by your web page when running on Android 4.2 or higher.

如果您不提供注释,则在 Android 4.2 或更高版本上运行时,您的网页将无法访问该方法。

The following example (taken from http://developer.android.com/guide/webapps/webview.html) shows that you can include the following class in your Android application:

以下示例(取自http://developer.android.com/guide/webapps/webview.html)表明您可以在 Android 应用程序中包含以下类:

public class WebAppInterface {
    Context mContext;

    /** Instantiate the interface and set the context */
    WebAppInterface(Context c) {
        mContext = c;
    }

    @JavascriptInterface   // must be added for API 17 or higher
    public void showToast(String toast) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}

and bind as

并绑定为

WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");

and then call from the HTML inside the WebView as

然后从 WebView 内的 HTML 调用

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>