我们公司目前进行的项目开发大多是Hybrid开发,也就是app里嵌入H5页面,所以Native端和H5端在有时候需要进行交互。比如H5界面有录制视频的需求,需要调起原生的摄像头功能,这在H5端肯定是无法实现的。因为H5实质上只是一个嵌入的webView,所需的api需要原生端进行提供。

这时候,我们就需要JSBridge作为Native端和H5端进行交互的工具,这个项目采用的是WebViewJavascriptBridge,具体API和介绍在这个官方文档里都有,不做详细说明了。

阅读了JSBridge之后,我们还需要一份由Native原生端提供的接口文档,上面详细的说明了我们应当调用他们的方法、回调参数以及需要我们提供给他们调用的方法。

接口文档示例如下图所示:

android h5调用原生 h5调用原生接口_JSON

下面来说说可能遇到的坑:

  1. 原生端接口文档不准确。事实上和与后端对接是一样的,接口文档不正确带来的问题就是无法交互成功,而且对于与原生端交互,最大的问题在于前端无法在本地调试,出了问题只有找原生端,解决问题效率非常低。本次项目我安装了vconsole,但是不知道为什么在原生端打开时无效,推测可能是原生端对于webView做了什么限制。这次项目,花费时间最多的就是接口文档这一块儿了,所以下次开发前一定要确认接口文档是否准确。
  2. registerHandler需要声明回调的参数,不然等于未注册这个方法。
bridge.registerHandler('svideoCallBackStatus', function(data) {
        callback(data);
      });

3.registerHandler方法也就是Native调用H5的js,需要提前调用。我在项目里处理是在页面的created生命周期里调用的。确保和原生端交互的时候已经注册。

4.项目中出现比如两次进入同一页面,调起JSBridge的时候,registerHandler方法会调用两次的问题。牛邦的林宇大神修改了初始化JSBridge的代码,加了对于回调函数的判重操作。避免了直接入队,导致反复调用的问题。修改后的代码如下:

/**
 * 原生端js桥
 */
export function setupWebViewJavascriptBridge(callback) {
  // 回调是否存在了
  let callbackExisted = false;
  if ((<any>window).WebViewJavascriptBridge) {
    return callback((<any>window).WebViewJavascriptBridge);
  }
  if ((<any>window).WVJBCallbacks) {
    (<any>window).WVJBCallbacks.forEach(cb => {
      if (JSON.stringify(cb) == JSON.stringify(callback)) {
        callbackExisted = true;
      }
    });
    if (!callbackExisted) {
      return (<any>window).WVJBCallbacks.push(callback);
    }
    return;
  }
  (<any>window).WVJBCallbacks = [callback];
  var WVJBIframe = document.createElement('iframe');
  WVJBIframe.style.display = 'none';
  WVJBIframe.src = 'https://__bridge_loaded__';
  document.documentElement.appendChild(WVJBIframe);
  setTimeout(function() {
    document.documentElement.removeChild(WVJBIframe);
  }, 0);
}