现在的 App 开发中,结合 H5 和原生控件混合开发是比较常见的做法,可降低开发成本、解决 UI 适配等。然而在某些场景中,H5 需要与原生做一些数据交换和事件处理。虽然 WebView 提供了相关 Js 调用的方法,但在 Android 早期版本(4.2 版本前)中发现存在严重的漏洞,所以我们这里不再讨论,而是使用现在比较常用的一个第三方框架——JsBridge 来实现。
JsBridge 的使用
JsBridge 的基本使用方法可查看作者的介绍,原生和 Js 的配置和使用方法介绍的比较清晰。Android 端可根据需要将 com.github.lzyzsd.jsbridge.BridgeWebView
做一个封装,初始化常用的 WebView 设置,以及 WebViewClient 和 WebChromeClient,打造你项目中通用的 WebView。另外,H5 前站现在普遍流行使用 Vue 框架,在接入 JsBridge 方法的时候出现了一些问题,在和前端同事一起探索后,实现了原生和 H5 的双向数据交互,并把 JsBridge 在 Vue 中的使用进行了封装。
JsBridge 在 Vue 的封装与交互
JsBridge 工具类
1 | /** |
引入
1 | import jsBridge from './utils/JSbridge.js' |
组件中使用
使用的方法名与 App 端约定好。
1、给 App 端发送数据1
jsBridge.callHandler(eventName, data, callback(reponseData))
参数说明:
- eventName (string): 必传, 与 App 端约定的事件名
- data (object): 非必传, 发送给 App 端的数据
- callback (function): 通信完成后,前端的回调,reponseData,是 App 端返回的数据
2、接受 App 端的数据1
jsBridge.registerHandler(eventName, callback(data, responseCallback))
参数说明:
- eventName (string): 必传,与 App 端约定的事件名
- callback (function): data: 是接受到的数据,responseCallback,通信完成后,传给 App 端的回调
问题解决
找不到处理 yy://__QUEUE_MESSAGE__/
意图的 Activity
异常如下:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=yy://__QUEUE_MESSAGE__/ flg=0x10000000 }
在 WebViewClient 的 shouldOverrideUrlLoading 中可以进行拦截 URL 跳转,实现在当前 WebView 加载网页链接,以及通过自定义 Uri 协议格式跳转页面(包括其他 App 的页面)。
Android 端出现此问题是你在这里做了跳转并返回了 true。翻阅 JsBridge 调用原理,其中一步是:Js 将消息内容放在 sendMessageQueue 中,并设置 iframe 的 src 为 yy://__QUEUE_MESSAGE__/
。所以如果你像上面说的那样进行了处理,这里就会异常,App 端收不到消息。
解决方案是:
处理你已知的要进行加载或跳转的协议,如 Http/Https 协议、自定义 Uri 协议等,返回 true,其他的情况,请:return super.shouldOverrideUrlLoading(view, url)
,交给系统处理(即:处理 JsBridge 的方法是这种情况)。