//notation: js file can only use this kind of comments//since comments will cause error when use in webview.loadurl,//comments will be remove by java use regexp(function() {  if (window.WebViewJavascriptBridge) {    return;  }    var messagingIframe;  var bizMessagingIframe;  var sendMessageQueue = [];  var receiveMessageQueue = [];  var messageHandlers = {};    var CUSTOM_PROTOCOL_SCHEME = 'yy';  var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';    var responseCallbacks = {};  var uniqueId = 1;    // 创立音讯index队列iframe  function _createQueueReadyIframe(doc) {    messagingIframe = doc.createElement('iframe');    messagingIframe.style.display = 'none';    doc.documentElement.appendChild(messagingIframe);  }  //创立音讯体队列iframe  function _createQueueReadyIframe4biz(doc) {    bizMessagingIframe = doc.createElement('iframe');    bizMessagingIframe.style.display = 'none';    doc.documentElement.appendChild(bizMessagingIframe);  }  //set default messageHandler  初始化默认的音讯线程  function init(messageHandler) {    if (WebViewJavascriptBridge._messageHandler) {      throw new Error('WebViewJavascriptBridge.init called twice');    }    WebViewJavascriptBridge._messageHandler = messageHandler;    var receivedMessages = receiveMessageQueue;    receiveMessageQueue = null;    for (var i = 0; i < receivedMessages.length; i++) {      _dispatchMessageFromNative(receivedMessages[i]);    }  }    // 发送  function send(data, responseCallback) {    _doSend({      data: data    }, responseCallback);  }    // 注册线程 往数组外面增加值  function registerHandler(handlerName, handler) {    messageHandlers[handlerName] = handler;  }  // 调用线程  function callHandler(handlerName, data, responseCallback) {    _doSend({      handlerName: handlerName,      data: data    }, responseCallback);  }    //sendMessage add message, 触发native解决 sendMessage  function _doSend(message, responseCallback) {    if (responseCallback) {      var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();      responseCallbacks[callbackId] = responseCallback;      message.callbackId = callbackId;    }        sendMessageQueue.push(message);    messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;  }    // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,因为android不能间接获取返回的内容,所以应用url shouldOverrideUrlLoading 的形式返回内容  function _fetchQueue() {    var messageQueueString = JSON.stringify(sendMessageQueue);    sendMessageQueue = [];    //android can't read directly the return data, so we can reload iframe src to communicate with java    bizMessagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);  }    //提供给native应用,  function _dispatchMessageFromNative(messageJSON) {    setTimeout(function() {      var message = JSON.parse(messageJSON);      var responseCallback;      //java call finished, now need to call js callback function      if (message.responseId) {        responseCallback = responseCallbacks[message.responseId];        if (!responseCallback) {          return;        }        responseCallback(message.responseData);        delete responseCallbacks[message.responseId];      } else {        //间接发送        if (message.callbackId) {          var callbackResponseId = message.callbackId;          responseCallback = function(responseData) {            _doSend({              responseId: callbackResponseId,              responseData: responseData            });          };        }                var handler = WebViewJavascriptBridge._messageHandler;        if (message.handlerName) {          handler = messageHandlers[message.handlerName];        }        //查找指定handler        try {          handler(message.data, responseCallback);        } catch (exception) {          if (typeof console != 'undefined') {            console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);          }        }      }    });  }    //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以  function _handleMessageFromNative(messageJSON) {    console.log(messageJSON);    if (receiveMessageQueue) {      receiveMessageQueue.push(messageJSON);    }    _dispatchMessageFromNative(messageJSON);      }    var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {    init: init,    send: send,    registerHandler: registerHandler,    callHandler: callHandler,    _fetchQueue: _fetchQueue,    _handleMessageFromNative: _handleMessageFromNative  };    var doc = document;  _createQueueReadyIframe(doc);  _createQueueReadyIframe4biz(doc);  var readyEvent = doc.createEvent('Events');  readyEvent.initEvent('WebViewJavascriptBridgeReady');  readyEvent.bridge = WebViewJavascriptBridge;  doc.dispatchEvent(readyEvent);})();

待过的某家公司中用于和原生交互的计划,当初这个文件也是从网上找的,拿来就用,没怎么细看。

最早咱们的Hybrid利用只是h5调用原生的一些办法,所以只应用了native向页面注入一个webview的变量,并在这个变量上挂载一些办法,在安卓上存在一些问题(?安全漏洞)。起初改用bridge,安全性和兼容性比拟好。bridge有一个小小的问题就是如果原生端不存在对应名称的办法,h5无奈晓得,所以h5须要做一套版本的判断,再进行办法的调用。

执行的操作

简略剖析一下:这个文件蕴含了一个立刻执行函数,代码加载后,做了几件事件:

  1. 定义协定scheme,相似http,这里定义为yy
  2. 创立音讯index队列iframe,这个iframe前面能够看到是h5端应用的;创立音讯体队列iframe,这个iframe能够看到是给原生端应用的。这两个iframe用于消息传递。
  3. 创立WebViewJavaScriptBridge对象并挂载到window上
  4. 创立Event对象,初始化事件名为WebViewJavaScriptBridgeReady的事件,并触发事件,示意bridge对象已筹备好,能够应用了。

bridge对象

bridge对象有6个办法,别离为init、send、registerHandler、callHandler、_fetchQueue、_handleMessageFromNative,办法的作用大抵能够见名知意。

  • init办法,用于设置默认的音讯处理函数,如果此时h5端的音讯接管队列不为空,则调用_dispatchMessageFromNative来散发解决队列中的音讯
  • send办法,用于h5端发送音讯,触发native去解决,调用_doSend将音讯塞进h5端的音讯发送队列,并将messagingIframe的src设置为发送的协定,触发iframe从新申请加载
  • registerHandler办法:用于定义音讯名称与音讯回调函数的映射,保留在messageHandlers对象上,提供js函数给native调用,在原生实现操作后,将数据通过回调函数传递给h5
  • callHandler办法:用于h5调用_doSend批改iframe src的形式将音讯和数据传递原生
  • _fetchQueue办法:提供给native应用的办法,将bizMessagingIframe的src设置为接管的协定,触发iframe从新申请,使原生获取到h5发送的音讯
  • _handleMessageFromNative办法:提供给native应用的办法,将音讯塞进h5的音讯接管队列,并进行音讯散发

大抵流程

1. H5调用Native

2. Native向H5传递

原理

H5调用Native的流程次要利用了iframe与原生端进行交互,通过批改iframe的src来触发原生端调用对应的操作,原生端监听到触发后,通过一系列操作后失去一个后果,再通过调用h5的回调函数,使h5能够解决原生返回的后果。

Native向h5传递有点相似h5的事件监听,h5注册一个名称用于标记操作,映射一个回调函数,原生端在用户做了某些操作后,获取到h5注册的操作对应的回调函数,并进行调用,将操作后果传递给h5。

参考

https://github.com/lzyzsd/JsB...

luffyjet/WebViewJavaScriptBridge

marcuswestin/WebViewJavascriptBridge

https://blog.csdn.net/weixin_...

https://blog.csdn.net/sinat_3...

Android与JS交互篇--JSBridge的应用