Android WebView 中 JavaScript 和 Native 通信方式

0、在开发 Hybrid App 的时候,经常需要处理 JavaScript 和 Native 交互的问题,其实从根本上说,是一个通信方式的问题,至于具体实现,其实有很多的方案。

1、JavascriptBridge

Android 中的 WebView 有 addJavascriptInterface 接口,该接口的功能是将一个 Java 对象注入到 WebView 的 window 对象中,即在 H5 页面运行的时候,在 window 对象中会增加一个元素,该元素包含 Java 对象中的方法。

例如:

private class JavascriptBridge {
    @JavascriptInterface
    public String run(String param) {
        // todo by param and return a result
    }
}
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JavascriptBridge(), "AppBridge");

这时候在 H5 页面就可以通过

var result = window.AppBridge.run('Hello World');

类似的方法进行调用 ,并可以获得由原生代码返回的结果。

该方法的安全性问题:

在 Android 4.2 即 API 17 以下,没有 @JavascriptInterface 注解,默认的情况下允许调用注入的 Java 对象的所有方法,因此存在利用反射的方式执行任意的 Java 方法的可能性,甚至可以执行某个进程。如果有心人在 H5 页面植入精心设计好的代码,那么在打开这个 H5 页面的时候,存在手机变成肉鸡的可能。

解决方案:

一个是从 Android 4.2 开始适配,另一个是不使用 addJavascriptInterface 而通过重写 onJsPrompt 方法。

其他注意点:

一个是代码混淆的时候需要对注入的对象做处理,不能混淆用到的方法名称。另一个是由 H5 页面发起的方法不是在主线程上运行的,需要随时注意跨线程的问题。还有一点是,系统默认在 window 对象中增加了 searchBoxJavaBridge_ 等对象,因此在启用 JavaScript 之后要加入以下代码:

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
    mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
    mWebView.removeJavascriptInterface("accessibility");
    mWebView.removeJavascriptInterface("accessibilityTraversal");
}

该段代码的作用是移除系统自动往里面添加的 Java 对象,防止被攻击者利用。

2、重写 onJsPrompt 方法

WebChromeClient 提供了一个方法:

public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
    return false;
}

该方法允许我们重写 JS 输入框的样式,即可以自定义在 H5 页面调用 prompt 方法时,浏览器所做出的响应。因此,通过重写该方法,我们可以通过 message 和 defaultValue 获得 JS 传递过来的参数,并通过 JsPromptResult 给 H5 页面返回相应的值。该方法虽然有一些投机取巧,通信协议可能也需要专门设计,但确实可以解决 JavascriptInterface 带来的安全性问题。

3、拦截 URL 跳转

网络上大多数的解决方案都是基于拦截 URL 跳转实现,即通过重写 shouldOverrideUrlLoading 方法提供的参数获得 H5 页面传递过来的参数,然后通过 loadUrl 方法执行一段 JavaScript 代码给 H5 页面返回值。这是一个比较方便也比较通用的方法,因为在 iOS 开发当中,使用这个方法进行交互也是很方便的,因此得到广泛的使用。网络上有很多开源的框架也是基于这个原理实现的,例如:https://github.com/lzyzsd/JsBridge 等。

4、其他

其实从根本上说,只要解决通信问题即可,其他像内建一个 Web 服务器通过 WebSocket 通信理论上也可以解决问题。只不过解决起来可能比较复杂。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值