鉴于 H5 丰富的表现力,产品决定将项目中的某个详情页改为 H5 展示,评论、点赞仍由原生实现,于是便需要原生与 H5 交互。之前对于这块少有涉及,恰巧合作的前端同事对于这块也不太熟悉,所以耗时良久。现在功能做得差不多了,稍微记录一下。
原生
先看下 WebView 的设置:
1 | class VygWebView(context: Context, attr: AttributeSet) : BaseWebView(context, attr) { |
所有的交互全部通过 Json 字符串来进行,双端协定对 Json 的解析规则。本地通过添加 VygJavaScriptInterface 实现 sendMessage 方法,来接受 H5 传递过来的消息,通过 sendMessageToWeb 向 H5 发送消息。
定义消息体如下:
1 | class MessageEntity : Serializable { |
下面来看消息解析:
1 | abstract class MessageParser(private val activity: VygBaseActivity, private val webView: VygWebView, |
getEvents 为根据消息 type 来取得具体的消息体 Content 类型及处理消息的类:
1 | public final class Events { |
看到消息处理类:
1 | class MessageHandler(private val events: Events, private val entity: MessageEntity, private val activity: VygBaseActivity, private val webView: VygWebView) { |
举例一个具体的消息处理类:
1 | class LoadImageHandler : MessageHandler.HandleCallback { |
根据修改页面的业务,定义所有的 Event:
1 | object ArticleEvents { |
消息解析这一套流程便完成了,根据 type 找到对应的消息处理类,然后传入 Content 进行处理。
H5
H5 除了界面渲染之外,还需要根据约定实现相关的方法:
1 | getNativeData: function() { |
然后调用原生方法时,也是组装好 Message,然后调用 sendMessage 方法即可:
1 | // 个人中心 |
至此两端的交互体系大体完成。
小坑
- 最好使用本地 html 文件来完成交互,可以比较方便的加载本地图片,前缀加上”file://“,同时 WebView 需要设置(具体效用尚未研究):
1
2
3settings.allowFileAccess = true
settings.allowFileAccessFromFileURLs = true
settings.allowUniversalAccessFromFileURLs = true - H5 调用本地方法需要 voyager.sendMessage,iOS 则是 voyager_sendMessage。