一、交互如何实现

交互实现的前提 —— WebView允许执行JS

WebSettings settings = myWebView.getSettings();
settings.setJavaScriptEnabled(true);

1.1 Java 调用 JS

调用方式:

/** 注意参数的传递需要符合JS的语法,用单引号或者反斜杠转义 */
String js = "javascript:javaCallJS(\"Java called JS.\")";

此时注意,javascript 这个词不能存在大写的状态,否则在低版本的Android手机上(Android 4.4版本以下)是无反应的,因为Android 4.4版本以下的手机的WebView内核是WebKit,Android 4.4版本以后WebView的内核为Chromium。

1.2 JS 调用 Java

实现JS调用Java也比较简单,通常只需要以下几步。

  • WebView开启JavaScript脚本执行(在开头已经说明)
  • WebView设置供JavaScript调用的交互接口。
  • 客户端和网页端编写调用对方的代码。

提供JavaScript调用的交互接口

public class MainActivity extends Activity {
@SuppressLint("JavascriptInterface")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
/** 添加交互接口 */
myWebView.addJavascriptInterface(new JsInteration(), "control");
    ....
}
/** 声明交互接口及具体的回调方法 */
public class JsInteration { @JavascriptInterface
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
}
}

网页端调用交互接口

function toastMessage(message) {
window.control.toastMessage(message)
}

二、疑问解答

2.1 Alert 无法弹出

没有设置WebChromeClient的原因,需要在webView设置WebChromeClient().

myWebView.setWebChromeClient(new WebChromeClient() {});

2.2 Uncaught ReferenceError: functionName is not defined

网页的js代码没有加载,就调用了js方法。解决方法是在网页加载完成之后调用js方法或者限制用户在页面加载完成之前不允许调用JS的事件,下面的代码是在网页加载完成后调用JS方法的实例:

myWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//在这里执行你想调用的js函数
}
});

2.3 Uncaught TypeError: Object [object Object] has no method

如果只在Android 4.2版本及以上的手机存在这个问题,4.2版本一下不存在这个问题,那么就是系统处于安全限制的问题了。通过查阅Android文档发现:

Caution: If you’ve set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page code (the method must also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 or higher.

中文大意为

警告:如果你的APP的tagSdk level是17或者是更高,你必须要在暴露给网页可调用的方法(这个方法必须是公开的)加上@JavascriptInterface注释。如果你不这样做的话,在4.2以以后的平台上,网页无法访问到你的方法。

两种解决方法
  • 将targetSdkVersion设置成17或更高,引入@JavascriptInterface注释
  • 自己创建一个注释接口名字为@JavascriptInterface,然后将其引入。注意这个接口不能混淆。链接:部分混淆代代码的方案

2.4 All WebView methods must be called on the same thread

E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, FYI main Looper is Looper (main, tid 1) {528712d4})
E/StrictMode( 1546): at android.webkit.WebView.checkThread(WebView.java:2063)
E/StrictMode( 1546): at android.webkit.WebView.loadUrl(WebView.java:794)
E/StrictMode( 1546): at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96)
E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
E/StrictMode( 1546): at android.os.Handler.dispatchMessage(Handler.java:102)
E/StrictMode( 1546): at android.os.Looper.loop(Looper.java:136)
E/StrictMode( 1546): at android.os.HandlerThread.run(HandlerThread.java:61)

此问题出现的原因是:在js调用后的Java回调线程并不是主线程。如打印日志可验证

ThreadInfo=Thread[WebViewCoreThread,5,main]

解决上述的异常,将webview操作放在主线程中即可。

webView.post(new Runnable() {
@Override
public void run() {
webView.loadUrl(YOUR_URL).
}
});

三、引申

JavaScript和Java的交互是在子线程上面进行的

因为JavaScript和Java交互是在子线程上面进行的,所以如果需要UI方面的修改操作,或者执行其他的操作,必须要考虑到线程安全的问题。这个在上面的 疑问解答4有所体现出来。

为何Android4.2版本之后需要使用@JavascriptInterface来进行注解

在JELLY_BEAN_MAR1之前JS的注入存在很大的漏洞,此漏洞会导致通过页面可以直接操作Android Native Application。而且随着Android版本的不断提高,对WebView的要求也是逐渐严格的,这样减少了对Android的安全存在的威胁。

链接: Android 4.2版本以下使用WebView组件addJavascriptInterface方法存在JS漏洞

最新文章

  1. ArcGIS Server For Linux 10.2.2安装
  2. [转]Java 常用排序算法/程序员必须掌握的 8大排序算法
  3. what's the CRSF ??
  4. [DNX]解决dnu restore时找不到Newtonsoft.Json的问题
  5. ChartDirector应用笔记(一)
  6. docker容器互联
  7. 8款超绚丽的jQuery焦点图动画
  8. Android开发之sharedpreferences 详解
  9. Git 多人协作的工作模式
  10. App 运营 推广相关
  11. BitNami-Redmine安装和VisualSVN-Server配合使用
  12. python基础操作_元组_字典操作
  13. C语言 变量的作用域和生命周期(转)
  14. SpringBoot之解决云服务器VPS在所处云端集群的内网不能解析域名的问题:java.net.UnknownHostException:abc.cn: Temporary failure in name resolution
  15. XVIII Open Cup named after E.V. Pankratiev. GP of Romania
  16. [3] TensorFlow 深层神经网络
  17. opencv学习之路(25)、轮廓查找与绘制(四)——正外接矩形
  18. SpringMVC工作原理示意图
  19. luogu 1004 方格取数
  20. java递归排序

热门文章

  1. CSS 自定义字体
  2. 最喜欢的算法(们) - Levenshtein distance
  3. 如何解决SoftekBarcode.dll加载失败的问题
  4. 7.4 MVC vs MVP
  5. Mac OS环境下配置Myeclipse2015的经验
  6. WINDOWS窗口风格 WS_OVERLAPPEDWINDOW
  7. 条件随机场理论分析CRF(Conditional Random Field)
  8. Java使用velocity导出word
  9. flashcache
  10. Linux 学习笔记(一) 入门