如果在 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
Android WebView addJavascriptInterface does not work if the webview is created in the callback of WebChromeClient#onCreateWindow
提问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 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).
即使我遇到了同样的问题,在再次浏览文档后,我发现如果您将 设置targetSdkVersion
为17 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>