移动应用功能越来越丰富,部分功能需要以 H5 方式来实现
这就需要 H5 与 Native 进行交互,我们使用 JSBridge 来进行二者通信
JSBridge 定义 Native 和 H5 的通信方式
Native 通过协定的桥对象调用 H5
H5 通过协定的桥对象调用 Native
一、交互方式
1、伪协议 url scheme(适用于所有设备)
伪协议 与 url 类似,H5 触发伪协议,系统按优先级判断:
- 是否是系统应用,是则打开系统应用
- 是否有 app 注册当前伪协议,有则打开该 app
- native 触发 url 事件,捕获该伪协议,解析伪协议,调用方法
具体过程:
-
H5 调用 Native
触发伪协议,例如:
window.location.href= 'xxx://event=a&data=b&successName=c&failName=d'
-
Native 调用 H5
H5 在 window 注册方法供 native 调用(同 API 交互方式中 Native 调用 H5 一样)
2、通过 API 交互
具体过程:
-
H5 调用 Native
1.1、 H5 调用 Android: native 通过 addJavascriptInterface 注册,之后供 H5 调用
1.2、 H5 调用 iOS:native 通过 javascriptCore(需 iOS7 以上) 注册,之后供 H5 调用
-
Native 调用 H5
2.1、 Android 调用 H5:H5 在 window 上注册方法,native 通过 loadUrl 调用 H5,4.4及以上版本可以通过 evaluateJavascript 调用
2.2、 iOS 调用 H5:H5 在 window 上注册方法,native 通过 stringByEvaluatingJavascriptFromString 调用 H5
3、区别
区别在于 H5 如何调用 Native 以及 Native 响应 H5 当前调用指定方法的方式 不一样
3.1 H5 如何调用 Native:
伪协议:
window.location.href = 'xxx://event=a&data=b&successName=c&failName=d'
API:
window.JSActionBridge.handlerAction(
event,
data,
successName,
failName
)
window.webkit.messageHandlers.JSActionBridge.postMessage({
method: 'handlerAction',
data: {
actionEvent: event,
paramsJsonValue: data,
successCallback: successName,
errorCallback: failName
}
})
3.2 Native 响应 H5 就不列出了
3.3 API 交互方式的好处:
- 在 H5 中写起来更简单,不用创建 URL 的方式
- H5 传递参数更方便,使用拦截 URL 的方式,参数需要拼接到 url 后面,如果含有特殊字符,则需要转义,否则解析参数会出错,如 & = ?
- 例如
window.location.href = 'xxx://event=a&data=http://www.baidu.com/xxx.html?p=2&successName=c&failName=d'
这里解析参数得到的不是想要的值,需要对 http://www.baidu.com/xxx.html?p=2 进行转义
二、方案
目前公司内部使用 API 方式交互(Android 需要 4.2 以上,iOS 需要 7 以上)
1、约定名称
原生通过 JSActionBridge 注册 JSBridge 对象
H5 通过 JSActionBridge 获取 JSBridge 对象
2、原生 JSBridge 对象注册
Android:
webView.addJavascriptInterface(new JSActionBridge(), "JSActionBridge")
iOS:
// 通过 javascriptCore 注册
self.context = [[JSContext alloc] int];
self.context[@"JSActionBridge"] = self.bridgeobj;
3、调用
3.1 Native 方法定义
Android:
/*
* @params {String} actionEvent: 需要调用的原生事件名、方法名
* @params {String|Object|Array} paramsJsonValue: 传给原生的参数,最好约定为 json 格式
* @params {String} successCallBack:调用原生方法成功后,需要执行的的回调函数名,该函数定义在 window 上
* @params {String} errorCallback:调用原生方法失败后,需要执行的的回调函数名,该函数定义在 window 上
*/
void handlerAction(String actionEvent, String paramsJsonValue, String successCallBack, String errorCallback)
3.2 H5 调用 Native
JSActionBridge.handlerAction(actionEvent, paramsJsonValue, successCallBack, errorCallback)
3.3 Native 调用 H5
Android 调用 H5
String callbackUrl = "javascript:" + callback + "(\"" + jsonData + "\")";
webView.loadUrl(callbackUrl);
iOS 调用 H5
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat: @"callBack(%@)", jsonData]];
三、数据约定
原生方法定义
void handlerAction(String actionEvent, String paramsJsonValue, String successCallBack, String errorCallback)
1、成功或失败回调函数都返回 json 数据
数据格式:
{
"code":0,
"desc":"success",
"data": nativeReturnData
}
2、约定 code === 0 时表示调用成功,否则失败
3、actionEvent 归类
- 跳转原生页面
首页、登录注册页等
- 获取原生数据
获取用户信息、获取设备信息等
- 调用原生功能
跳转新页面、唤醒密码输入框、查看网络状态、设置标题等
- 其他
四、JSBridge 封装
1、协定:
- Android 传送字符串
- iOS 传送 json
2、successCallBack/errorCallback 回调数据格式:
{
"code":0,
"desc":"success",
"data": nativeData
}
3、JSBridge 封装
import { isIOS, isAndroid, isApp } from './utils.js'
const JSBridge = {
isApp,
// APP离线环境
isOfflineApp: isApp && location.protocol === 'file:',
// H5 调用 App
/**
* 调用 App 方法
* @param event:事件名称
* @param data:json 数据
* @param successCallBack: 成功回调
* @param failCallBack: 失败回调
* @returns {Promise