本文共 3766 字,大约阅读时间需要 12 分钟。
假如生活欺骗了你,假如工作到处不顺,请放松心态,提升自己,终有一天你会适应,然后。。。。。。。。。。。。。。。
本篇是面试小问题专栏的开篇文章,由于是面试小问题的解答,所以所有的文章都会力求把问题说明白的同时精简字数,可能有理解不到位的地方后续会慢慢完善。
h5可以作为移动端跨平台的一种方式,其他方式还有rnjs,flutter,weekx等,android或者ios为了实现和js的交互都提供了原生方法,但都存在一定的问题,这时jsbridge就诞生了。
android原生和js交互方式,调用js,loadurl通用,evaluateJavascript支持回调但都涉及版本问题,js调用原生不同版本又设置到安全问题,虽然新版利用@JavascriptInterface 解决了安全问题但现实中依然有很多低版本。
jsbridge 优点说明:
1 统一android ,ios两边的调用方式,使绑定和调用函数接口统一,
2 完美解决安全性问题和回调函数问题。
原理说明:
交互通道:
要实现原生和js交互首先需要一条双方交互的通道,一般的jsbridge都是利用拦截prompt函数,webView端拦截了js端发送的prompt函数,可以获取上面的文本。原生执行js还是利用原来的loadurl。
重写webView和 WebChromeClient,拦截prompt。
public static class WebChromeClientEx extends WebChromeClient { public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) { Logger.d("JsBridge","onJsPrompt: " + message); try { //根据协议进行解析 JSONObject jsonObject = new JSONObject(message); if (JavascriptBridge.matchBridgeProtocol(jsonObject)) { result.confirm("prompt ok"); JavascriptBridge.onGetDataFromJs(view, jsonObject); } else { result.confirm("data does not match bridge protocol"); } } catch (Exception e) { e.printStackTrace(); result.confirm("exception"); } return true; } public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { if (view instanceof BaseWebView) { SimpleToastHelper.showShortToast(view.getContext(), message); } result.confirm(); return true; } public boolean onJsAlert(WebView view, String url, String message, JsResult result) { if (view instanceof BaseWebView) { SimpleToastHelper.showShortToast(view.getContext(), message); } result.confirm(); return true; } }
定义协议:
js调用原生,会通过调用prompt函数,webView获取到prompt传递的文本(协议),根据自定义协议解析文本,执行特定原生函数。
js端如何调用原生的函数和回调如何处理:
native(原生)的函数A会被js调用,首先A和实现会被存储到本地的map中,然后native端回调用js端写好的注册函数,在对应的js端生成一个代表原生函数A的js函数B(其实两者之间没有必然联系,不想系统提供的js调用native的方式,没有注册对象,这样就保证了安全性),然后js调用想调用原生A函数时,就调用js函数B,利用prompt把调用原生A的协议传过去,onjsprompt拦截协议,调用本地A函数。
所以jsbridge都会提供H5端注册代码用于生成js的javascriptBridge对象,类似
(function () {
if (window.bridge) { return; }window.bridge = {};
var messages = {}; var call_id = 0;native函数需要调用register函数,在h5端生成对应的函数
bridge.register = function (name) {
if (this[name]) { return; } this[name] = function (params, callback) { invokeNative(name, params, callback); }; };bridge.obtain = function (id) {
return JSON.stringify(messages[id].params); };bridge.callback = function (id, data) {
var message = messages[id]; if (!message) { return; }if (message.callback) {
message.callback(JSON.parse(data)); } delete messages[id]; };最终实现调用原生的方法 prompt
function invokeNative (name, params, callback) {
call_id ++; messages[call_id] = {'params' : params, 'callback' : callback};if (navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Adr') > -1) {
prompt(JSON.stringify({'cmd':name, 'id':call_id, 'params':params}), ''); } else { var iframe = document.createElement('iframe'); iframe.src = 'bridge://invoke.native.method?handler=' + name + '&id=' + call_id; iframe.style.display = 'none'; document.documentElement.appendChild(iframe); setTimeout(function () { document.documentElement.removeChild(iframe); }, 0); } } })();原生调用js如何实现回调:
可以Native根据协议生成js对象,webView加载网页时将本地js注入到网页中,原生调用注入js中的函数,js端接收调用首先调用js函数,然后根据协议调用原生端的对调函数。
jsbridge简单介绍就到这里。
转载地址:http://aipei.baihongyu.com/