共计 2194 个字符,预计需要花费 6 分钟才能阅读完成。
HybridAPP 通过 JSBridge 提供调用 Native 功能的接口 ,让混合开发中的『前端部分』可以方便地使用地址位置、摄像头甚至支付等 Native 功能。它的核心是 构建 Native 和非 Native 间消息通信的通道 ,而且是 双向通信的通道。
JSBridge 的实现原理
js 调用 Native
注入 api/ 对象
原理:通过 WebView 提供的接口向 js 的 context(window)注入一个对象或者方法,js 调用时,直接执行对应的 Native 代码逻辑
iOS
UIWebVIew(iOS2+)和 WKWebView(iOS8+)的调用方式有所区别
// 假设 ios 客户端约定方法名为 nativeBridge
//UIWebView
window.nativeBridge(message);
//WKWebView
window.webkit.messageHandlers.nativeBridge.postMessage(message);
Android
原理:通过 WebView 提供的 addJavascriptInterface
方法给浏览器 window
注入一个命名空间,然后给 Web 增加一些可以操作 Java 的反射。
// addJavascriptInterface
mWebView.addJavascriptInterface(new Class(), 'android');
//@JavascriptInterface
public class Class(){
@JavascriptInterface
public void method(){}
}
// js 代码
window.android.method();
在 4.2 之前,Android 注入 JavaScript 对象的接口是 addJavascriptInterface,但是这个接口有漏洞,可以被不法分子利用,危害用户的安全,因此在 4.2 中引入新的接口 @JavascriptInterface(上面代码中使用的)来替代这个接口,解决安全问题。
拦截 URL scheme
iOS
在 UIWebView 内发起的所有网络请求,都可以 通过 delegate 函数在 Native 层得到通知。这样,我们就可以在 UIWebView 内发起一个自定义的网络请求,通常是这样的格式:jsbridge://methodName?param1=value1¶m2=value2
于是 Native 拦截的请求中,我们只要发现是 jsbridge:// 开头的地址,就不进行内容的加载,转而执行相应的调用逻辑。
缺点:
- 使用 iframe.src 发送 URL SCHEME 会有 url 长度的隐患。
- 创建请求,需要一定的耗时,比注入 API 的方式调用同样的功能,耗时会较长。
即使 URL scheme 链接有以上缺点,但因为它 支持 iOS6,所以为了实现兼容很多方案会使用这种方式
Android逻辑与 iOS 相似
改写浏览器原有对象
使用 prompt,console.log,alert 方式,在 android webview 这一层可以重写这些方法。
一般常使用 prompt,因为这个在 js 里使用的不多,用来和 native 通讯副作用比较少。
prompt 简单举例说明,Web 页面通过调用 prompt()
方法,安卓客户端通过监听 onJsPrompt
事件,拦截传入的参数,如果参数符合一定协议规范,那么就解析参数,扔给后续的 Java 去处理。这种协议规范,最好是跟 iOS 的协议规范一样,这样跨端调起协议是一致的,但具体实现不一样而已。比如:hybrid://action?arg1=1
这样的协议,而其他格式的 prompt
参数,是不会监听的,即除了 hybrid://action?arg1=1
这样的规范协议,prompt
还是原来的prompt
。
Native 调用 JS
Native 调用 js 实际就是执行拼接 js 字符串,从外部调用对应方法,返回 js 执行结果。因此 js 方法必须放在全局的 Window 上
iOS
是通过 UIWebView
组件的 stringByEvaluatingJavaScriptFromString
方法来实现的,该方法返回 js 脚本的执行结果。
//UIWebView
result = [uiWebview stringByEvaluatingJavaScriptFromString:javaScriptString];
//WKWebView
[wkWebView evaluateJavaScript:javaScriptString completionHandler:completionHandler];
Android
在 Kitkat(4.4)之前是使用 webview 的 loadUrl
进行调用的:
webView.loadUrl("javascript:JSBridge.trigger('webviewReady')");
而 Kitkat 之后的版本,也可以用 evaluateJavascript 方法实现:
webView.evaluateJavascript(javaScriptString, new ValueCallback<String>() {
@Override
publicvoidonReceiveValue(String value){}});
参考:
jsbridge 的原理
Hybrid 开发:JsBridge – Web 和客户端的桥
H5 与 Native 交互之 JSBridge 技术