如果在 WebChromeClient#onCreateWindow 的回调中创建了 webview,则 Android WebView addJavascriptInterface 不起作用 [英] Android WebView addJavascriptInterface does not work if the webview is created in the callback of WebChromeClient#onCreateWindow

查看:38
本文介绍了如果在 WebChromeClient#onCreateWindow 的回调中创建了 webview,则 Android WebView addJavascriptInterface 不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

主活动

public class MainActivity extends Activity {WebView mWebView1;WebView mWebView2;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);最终 FrameLayout mainFrame = (FrameLayout) this.findViewById(R.id.mainFrame);mWebView1 = new WebView(this);mWebView1.getSettings().setJavaScriptEnabled(true);mWebView1.getSettings().setSupportMultipleWindows(true);mWebView1.setWebViewClient(new WebViewClient() {@覆盖public boolean shouldOverrideUrlLoading(WebView view, String url) {返回假;}});mWebView1.setWebChromeClient(new WebChromeClient() {@覆盖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() {@覆盖public void onConsoleMessage(String message, int lineNumber, String sourceID) {Log.d("WebView", "Line:" + lineNumber + ", " + message);}});mWebView2.addJavascriptInterface(新对象(){@JavascriptInterface公共无效你好2(){}}, "AndroidFunction2");((WebViewTransport)resultMsg.obj).setWebView(mWebView2);resultMsg.sendToTarget();mainFrame.addView(mWebView2);返回真;}});mWebView1.addJavascriptInterface(新对象(){@JavascriptInterface公共无效你好1(){}}, "AndroidFunction1");mWebView1.loadUrl("file:///sdcard/test_1.html");mainFrame.addView(mWebView1);}}

还有两个网页,

test_1.html:

<身体><a href="test_2.html" target="_blank">转到测试 2</a><div><a href="javascript:alert(typeof AndroidFunction1);">警报(AndroidFunction1 的类型);</a>

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

test_2.html

<身体><div><a href="javascript:alert(AndroidFunction2);">警报(AndroidFunction2);</a>

<div><a href="javascript:alert(typeof window.AndroidFunction2);">警报(窗口类型.AndroidFunction2);</a>

解决方案

即使我遇到了同样的问题,再次浏览文档后我发现如果您将 targetSdkVersion 设置为 17 或更高,您必须将 @JavascriptInterface 批注添加到您希望可用于 JavaScript 的任何方法(该方法也必须是公共的).

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

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

public class WebAppInterface {上下文 mContext;/** 实例化接口并设置上下文 */WebAppInterface(上下文c){mContext = c;}@JavascriptInterface//必须为 API 17 或更高版本添加公共无效showToast(字符串吐司){Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();}}

并绑定为

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

然后从WebView内部的HTML调用

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')"/><script type="text/javascript">功能显示AndroidToast(吐司){Android.showToast(toast);}

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?

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:

<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

<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>

解决方案

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

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

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:

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

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

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

这篇关于如果在 WebChromeClient#onCreateWindow 的回调中创建了 webview,则 Android WebView addJavascriptInterface 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
移动开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆