一、交互如何实现

交互实现的前提 —— 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漏洞

Android WebView 总结 —— Java和JavaScript交互的更多相关文章

  1. android webview与 java与javascript的交互

    webView.getSettings().setJavaScriptEnabled(true);//打开就可以用js的功能   webView.getSettings().setJavaScript ...

  2. WebView上实现Java与JavaScript交互

    在安卓开发上,考虑到开发效率和界面更新,有时使用WebView结合web页面技术,可以快速迭代地开发移动应用.WebView加载资源的速度并不慢,但是如果资源多了,就很慢.图片.css.js.html ...

  3. Android 中Java和JavaScript交互入门

    如何实现JavaScript 和java 交互 实现Java和js交互十分便捷.通常只需要以下几步. WebView开启JavaScript脚本执行 WebView设置供JavaScript调用的交互 ...

  4. Android中Java和JavaScript交互

    Android提供了一个很强大的WebView控件用来处理Web网页,而在网页中,JavaScript又是一个很举足轻重的脚本.本文将介绍如何实现Java代码和Javascript代码的相互调用. 如 ...

  5. WebView中Java与JavaScript的交互

    原文首发于微信公众号:jzman-blog,欢迎关注交流! Android 开发过程中 WebView 的使用比较广泛,常用来加载网页,比如使用 WebView 加载新闻页面.使用 WebView 打 ...

  6. webview中java与js交互

    WebView提供了在Android应用中展示网页的强大功能.也是目前Hybird app的大力发展的基础.作为Android系统的一个非常重要的组件,它提供两方面的强大的能力:对HTML的解析,布局 ...

  7. 用ScriptEngine在java中和javascript交互的例子(JDK6新特性)

    package demo7; import java.util.Arrays; import java.util.List; import javax.script.Invocable; import ...

  8. Android WebView 开发教程

    声明在先:必须在AndroidMainfest.xml 里面声明权限,否则在Java里面编写的所有WebView浏览网页的代码都无法正常使用 <uses-permission android:n ...

  9. Android WebView 加载超长 JS 数据

    在之前的文章里面,我总结过WebView如何与网页交互,也就是Java如何和JS交互 —— Android WebView 总结 —— Java和JavaScript交互. 基于这篇文章,我们基本上能 ...

随机推荐

  1. SVN修改用户名与密码

    由于在svn的界面中并没有为我们提供直接更换用户名密码的地方,所以一旦我们需要更换用户名的就需要自己想一些办法. 解决方案如下: 在Eclipse使用SVN的过程中大多数人往往习惯把访问SVN的用户名 ...

  2. NOI 4976:硬币

    描述 宇航员Bob有一天来到火星上,他有收集硬币的习惯.于是他将火星上所有面值的硬币都收集起来了,一共有n种,每种只有一个:面值分别为a1,a2- an. Bob在机场看到了一个特别喜欢的礼物,想买来 ...

  3. ubuntu安装日文分词软件MeCab及其Python插件

    1.从官网上下载三个包: http://taku910.github.io/mecab/ mecab-0.996 mecab-0.996.tar.gz mecab-ipadic-2.7.0-20070 ...

  4. html5 datepicke

    最近在看html5新特性,对于input中date类型的显示想自定义,但不知道如何解决!有没有关注过的或已解决的给提供个方案??静等佳音.

  5. Eclipse 包排版问题

    问题描述: 在Eclipse中,项目结构如下所示: 这样的显示方式,查找内容太不方便.使用不习惯. 解决方法: Eclipse中默认包的显示方式为flat,使其改为Hierarchical. 操作步骤 ...

  6. css各项水平居中

    当被设置元素为块状元素时用text-align:center就不起作用了,这也分两种情况,定宽块状元素和不定宽块状元素. 一.定宽块状元素:快状元素的宽度width为固定值,之后我们可以将左右marg ...

  7. java 内存机制

    1.Java的内存机制 Java 把内存划分成两种:一种是栈内存,另一种是堆内存.在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在 ...

  8. 初入liunx的一些基本的知识

    本系列的博客来自于:http://www.92csz.com/study/linux/ 在此,感谢原作者提供的入门知识 这个系列的博客的目的在于将比较常用的liunx命令从作者的文章中摘录下来,供自己 ...

  9. [ASE][Daily Scrum]12.12

    好久没有写daliy scrum了…… 目前看,我们的无限地图,AI以及计分都差不多成型了,不过还有很多bug在调整当中 今天要做的是 Zhao 调通分数&聊天服务器 Yiming Shili ...

  10. Android度量单位说明(DIP,DP,PX,SP) (转帖)

    (一)概念 dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和QVGA 推荐使用这个,不 ...