关于jsBridge
最近在开发移动端项目时,需要用到jsBridge,因此总结下自己了解jsbridge的过程
一、为什么会用到jsbridge
在混合开发中的前端部分(javascript)调用native的功能时需要用到jsbriage,例如:分享时我们需要打开微信、QQ,以及调用摄像头,获取地理位置等;因为app内嵌的H5页面中我们无法调出这些功能。
在了解jsbridge前,我们需要了解下整个移动端的大致发展流程,可能会更容易理解了
最早之前,1)是有原生的IOS和Android,开发成本高;
2)随着H5标准的发布,就有了webapp的概念,也就是在触屏浏览器里运行的,宿主是浏览器,不再是操作系统。依赖于浏览器的处理能量并且与原生交互受限;为了解决WebApp 与原生接口交互受限。交互体验差,便提出了混合开发(hybrid)的概念,称作混合模式移动应用,介于WebApp与Native App两者之间的开发技术;(ios和android依然是2套代码);用html+js来写页面的逻辑,然后由native通过jsbriage等方法提供统一的api,最终的页面也是在webview中显
3)跨平台,例如react native,weex,以及大火的flutter(并没有相关研究,只是举个例子)
最后附上相关链接:https://zhuanlan.zhihu.com/p/79495800 ,https://zhuanlan.zhihu.com/p/58691238
二、怎么使用(封装)jsbridge
在使用jsbridge之前,需要知道什么是jsbridge?
jsbridge是一个 iOS/OSX 桥或Android/js桥,用于在 WKWebViews、UIWebViews 和 WebViews 中的 Obj-C 和 JavaScript 之间发送消息
由于javascript运行在一个单独的 JS Context 中,与原生运行环境天然隔离,jsbriage就是来建立这两者之间的通道
现在你知道jsbridge是native和非native之前通信的通道,而且这个通道是双向的,js可以通过jsbridge调用native的原生api,native也可以向js发送消息,传达native调用后的状态
双向通信的通道:
- JS 向 Native 发送消息: 调用相关功能、通知 Native 当前 JS 的相关状态等。
- Native 向 JS 发送消息: 回溯调用结果、消息推送、通知 JS 当前 Native 的状态等
那么jsbriage是如何在native和js之前通信的呢?
三、javascript是如何调用native的?
javascript调用native的方式有2种:注入API 和 拦截URL SCHEME
1)注入API :向JavaScript的window注入native的方法,让javascript可以直接调用原生native的的逻辑,达到 JavaScript 调用 Native 的目的。
在java中注册一个处理函数,让js可以调用它
webView.registerHandler("submitFromWeb", new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { Log.i(TAG, "handler = submitFromWeb, data from web = " + data); function.onCallBack("submitFromWeb exe, response data from Java"); } });
在js中调用这个事件 :WebViewJavascriptBridge是native为web视图创建的javascript的桥,而实例化的一个对象
WebViewJavascriptBridge.callHandler( 'submitFromWeb' , {'param': str1} , function(responseData) { document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData } );
2)拦截URL SCHEME
URL SCHEME 是一种类似于url的链接,为了方便app之间直接互相调用设计
拦截 URL SCHEME 的主要流程是:Web 端通过某种方式(例如 iframe.src)发送 URL Scheme 请求,之后 Native 拦截到请求并根据 URL SCHEME(包括所带的参数)进行相关操作。
https://img.lifecdn.com/tps/123.png
我们可以自定义协议,改成
jsbridge://methodName?param1=value1¶m2=value2
。Native拦截
jsbridge
开头的网络请求,做出对应的动作。最常见的做法就是创建一个隐藏的iframe来实现通信。
在实现过程中,这种方式有一定的缺陷:使用 iframe.src 发送 URL SCHEME 会有 url 长度的隐患。
缺点:创建请求,需要一定的耗时,比注入 API 的方式调用同样的功能,耗时会较长
四、native调用javascript的方法
native端调用js的方法:需要js在WebViewJavascriptBridge上注册一个js事件,然后java可以通过事件名来调用这个事件;
registerHandler
在Native端定义(是JSBridge对象的一个方法),由前端来注册,js注册了事件之后,native端就可以来调用
native调用主动调用js有2种情况:一种native主动触发前端注册的事件,通知前端页面的状态变化;另一种是前端调用native的回调
WebViewJavascriptBridge.registerHandler("functionInJs", function(data, responseCallback) { document.getElementById("show").innerHTML = ("data from Java: = " + data); var responseData = "Javascript Says Right back aka!"; responseCallback(responseData); });
Java可以通过以下方式调用这个js处理函数“functionInJs”:
webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) { } });
实际项目中使用:
export function setupWebViewJavascriptBridge (callback) { if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge) } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback) } window.WVJBCallbacks = [callback] var WVJBIframe = document.createElement('iframe') WVJBIframe.style.display = 'none' WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__' document.documentElement.appendChild(WVJBIframe) setTimeout(function () { document.documentElement.removeChild(WVJBIframe) }, 0) }
js调用:
var js_bridge = require("../../utils/nativejsbridge.js"); var data = { title:'001', desc:'001测试', image:'http://img', shareUrl: 'http://....' }; js_bridge .setupWebViewJavascriptBridge(function(bridge) { bridge.callHandler("friend", data, function( // 这里的bridge就是window.WebViewJavascriptBridge这个对象,然后去调用native 的shareFriend事件,shareData是发送给native的数据, data, responseCallback ) { console.log('001') }); });
最后附上一些文档,方便查阅:
https://segmentfault.com/a/1190000010356403
https://www.jianshu.com/p/be491bfbca0d
https://blog.csdn.net/yuzhengfei7/article/details/93468914
https://github.com/lzyzsd/JsBridge
https://github.com/marcuswestin/WebViewJavascriptBridge
只是自己对jsbridge的一些浅显的了解,勿喷