• 七月
  • 08
  • load

(Hybrid)Android WebView Java和Js交互的三种方式 2019-07-08 00:08:26

Hybrid,就是网页和原生的交互,既能保证动态更新效果,还能跨平台,但这个过程,却产生了一系列的学问。如js调用java会产生怎样的问题。

Java调用js

一行代码即可完成

这里有两个问题

1.对于Java来讲,执行是异步的。

2.对于webView来说,他只是执行了一个js函数,如果有返回值,它没有赋值给任何变量。想解决这个问题,大概就要靠回调函数吧。

难道没有其他方法吗?有,用mWebView.evaluateJavascript,不仅执行效率比loadUrl高,而且还能获取js的返回值。

那为什么不直接用这个?因为这玩意4.4以上才能用,所以一般是混着用。

示例:

js代码:

 

Js调用Java

1.首先,创建一个给js调用的类(其实也可以不创建),示例:

为了安全,从4.2开始,js可调用的java方法需要添加@JavascriptInterface注解,如代码中的toast,如果js想调用这个toast,我需要添加注解(就当是给h5授权特定的方法吧)

2.把这个对象暴露给js

3.写h5页面

这个时候你调用toast应该就没问题了,但如果你尝试去调用没有注解过的方法,会出现类似这样的错误:

"Uncaught TypeError: Object [object Object] has no method 'cannotCall'", source: file:///android_asset/test.html (21)

当然,并不是说一定调用不了,刚刚也提到,从4.2开始,js可调用的java方法需要添加@JavascriptInterface注解,也就是说,4.2以下是可以调用的。

(toast写错了,应该是4.2以下)

 

能不能修复这个问题?

最简单的方式就是直接不兼容4.2以下的版本了,当然非要兼容的话那就是不能用addJavascriptInterface的方式了。

方法1:shouldOverrideUrlLoading拦截

其实就是浏览器想请求某个页面,然后拦截下来,url可以传递些字符串的嘛,那就捕获字符串执行某些操作就行了。

但有个缺陷,对于webview来讲,他只是想跳转页面,并不是想执行一个原生方法,因此想获取返回值还是挺麻烦的。不过我们只要在js里制定一个回调函数就行了。

然而,这种方式只是获取到一个字符串,因此,我们还需要制定一种格式,用于传递参数,例如这样:

方法名|参数1|参数2...

至于调用的方式,可以反射,也可以判断字符串,如果使用反射的话,最好要做下验证什么的,例如加个JavascriptInterface注解,不然就是完美继承了4.2以下的bug,并把该bug向上兼容,还新增了难以获取返回值的问题

具体怎么封装,就看业务逻辑了,这里给出一种演示方式(注意:这里只是根据思路提供的演示,不建议实际开发直接使用)

创建一个继承WebViewClient的类

创建webview的时候把client set进去

使用方式:

方法2:prompt拦截

对话框里常见有alert、confirm、prompt,为什么要使用prompt?并不是因为prompt不常用就欺负它,而是因为在WebChromeClient里,前两个回调方法里包含了JsResult,而prompt则是继承了JsResult的JsPromptResult,JsPromptResult的confirm是可以传递String,通过它,我们可以传递任意值给js,可以视为提供返回值了。

不过格式还是要制定一下,实际开发里建议用json,我们就随意制定一下:

方法名|参数1|参数2...

示例(注意:这里只是根据思路提供的演示,不建议实际开发直接使用):

创建webview的时候把ChromeClient set进去

前端:

这么看来,还是拦截prompt比较好,既避免了4.2以下的问题,还不会像shouldOverrideUrlLoading那么麻烦。

那么下一个问题来了,还是觉得麻烦,有没有更加方便的方法?

说不上有,那就是使用开源库了,如:

safe-java-js-webView-bridge:https://github.com/pedant/safe-java-js-webview-bridge

JsBridge:https://github.com/lzyzsd/JsBridge

使用方法就不介绍了,他们文档有写。

 

代码已提交到:https://gitee.com/sqsxtest/hybrid

正在加载评论...

0 / 240

警告

确定