APP和H5通信-JsBridge

背景

在移动开发领域,原生应用嵌入网页(H5)可以实现一套代码多端使用,那么原生应用(APP)和网页(H5)之间的通信就非常重要。

JsBridge作为一种实现此类通信的工具,用于实现原生应用和嵌入其中的网页之间的通信。

H5与native交互,本质上来说就两种调用:

  1. JavaScript 调用 native 方法
  2. native 调用 JavaScript 方法

JavaScript调用native方法有两种方式:

  1. 注入,native 往 webview 的 window 对象中添加一些原生方法,h5可以通过注入的方法来调用 app 的原生能力
  2. 拦截,H5通过与 native 之间的协议发送请求,native拦截请求再去调用 app 原生能力

本文主要介绍H5端与App(android和ios)之间通信使用方式。

代码实现

实现步骤:

这段代码实现的是 APP(Android 和 iOS) 和 H5 之间的通信。这个通信过程主要依赖于 WebViewJavascriptBridge 这个桥接库。这里是具体的流程:

  1. 初始化 WebViewJavascriptBridge 对象:

    • 对于 Android,如果 WebViewJavascriptBridge 对象已经存在,则直接使用;如果不存在,则在 'WebViewJavascriptBridgeReady' 事件触发时获取 WebViewJavascriptBridge 对象。

    • 对于 iOS,如果 WebViewJavascriptBridge 对象已经存在,直接使用;如果不存在,则创建一个隐藏的 iframe 来触发 WebViewJavascriptBridge 的初始化,并在初始化完成后通过 WVJBCallbacks 回调数组来获取 WebViewJavascriptBridge 对象。

  2. 注册事件:

    提供了 callHandlerregisterHandler 两个方法,分别用于在 JS 中调用 APP 端的方法和注册供 APP 端调用的 JS 方法。

  3. 调用方法:

    当 APP 或 JS 需要调用对方的方法时,只需调用 callHandlerregisterHandler 方法即可。

js 复制代码
const { userAgent } = navigator;
const isAndroid = userAgent.indexOf('android') > -1; // android终端

/**
 * Android  与安卓交互时:
 *      1、不调用这个函数安卓无法调用 H5 注册的事件函数;
 *      2、但是 H5 可以正常调用安卓注册的事件函数;
 *      3、还必须在 setupWebViewJavascriptBridge 中执行 bridge.init 方法,否则:
 *          ①、安卓依然无法调用 H5 注册的事件函数
 *          ①、H5 正常调用安卓事件函数后的回调函数无法正常执行
 *
 * @param {*} callback
 */
function androidFn(callback) {
  if (window.WebViewJavascriptBridge) {
    callback(window.WebViewJavascriptBridge);
  } else {
    document.addEventListener(
      'WebViewJavascriptBridgeReady',
      () => {
        callback(window.WebViewJavascriptBridge);
      },
      false,
    );
  }
}

/**
 * IOS 与 IOS 交互时,使用这个函数即可,别的操作都不需要执行
 */
function iosFn(callback) {
  if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge); }
  if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
  window.WVJBCallbacks = [callback];
  const WVJBIframe = document.createElement('iframe');
  WVJBIframe.style.display = 'none';
  WVJBIframe.src = 'https://__BRIDGE_LOADED__';
  document.documentElement.appendChild(WVJBIframe);
  setTimeout(() => { document.documentElement.removeChild(WVJBIframe); }, 0);
}

/**
 * 注册 setupWebViewJavascriptBridge 方法
 *  之所以不将上面两个方法融合成一个方法,是因为放在一起,那么就只有 iosFuntion 中相关的方法体生效
 */
const setupWebViewJavascriptBridge = isAndroid ? androidFn : iosFn;

/**
 * 这里如果不做判断是不是安卓,而是直接就执行下面的方法,就会导致
 *      1、IOS 无法调用 H5 这边注册的事件函数
 *      2、H5 可以正常调用 IOS 这边的事件函数,并且 H5 的回调函数可以正常执行
 */
if (isAndroid) {
  /**
     * 与安卓交互时,不调用这个函数会导致:
     *      1、H5 可以正常调用 安卓这边的事件函数,但是无法再调用到 H5 的回调函数
     *
     * 前提 setupWebViewJavascriptBridge 这个函数使用的是 andoirFunction 这个,否则还是会导致上面 1 的现象出现
     */
  setupWebViewJavascriptBridge((bridge) => {
    console.log('打印***bridge', bridge);
    // 注册 H5 界面的默认接收函数(与安卓交互时,不注册这个事件无法接收回调函数)
    bridge.init((message, responseCallback) => {
      responseCallback('JS 初始化');
    });
  });
}

export default {
  // js调APP方法 (参数分别为:app提供的方法名  传给app的数据  回调)
  callHandler(name, params, callback) {
    setupWebViewJavascriptBridge((bridge) => {
      bridge.callHandler(name, params, callback);
    });
  },

  // APP调js方法 (参数分别为:js提供的方法名  回调)
  registerHandler(name, callback) {
    setupWebViewJavascriptBridge((bridge) => {
      bridge.registerHandler(name, (data, responseCallback) => {
        callback(data, responseCallback);
      });
    });
  },
};

使用 JSBridge 总结:

1、跟 IOS 交互的时候,只需要且必须注册 iosFuntion 方法即可,不能在 setupWebViewJavascriptBridge 中执行 bridge.init 方法,否则 IOS 无法调用到 H5 的注册函数;

2、与安卓进行交互的时候

  • 使用 iosFuntion,就可以实现 H5 调用 安卓的注册函数,但是安卓无法调用 H5 的注册函数, 并且 H5 调用安卓成功后的回调函数也无法执行
  • 使用 andoirFunction 并且要在 setupWebViewJavascriptBridge 中执行 bridge.init 方法, 安卓才可以正常调用 H5 的回调函数,并且 H5 调用安卓成功后的回调函数也可以正常执行了

H5使用

h5获取app返回的数据:

js 复制代码
jsBridge.callHandler('getAppUserInfo', { title: '首页' }, (data) => {
    console.log('获取app返回的数据', data);
 });

app获取h5返回的数据:

js 复制代码
 jsBridge.registerHandler('getInfo', (data, responseCallback) => {
    console.log('打印***get app data', data);
    responseCallback('我是返回的数据');
  });

两者都可通信,只要一方使用registerHandler注册了事件,另一方通过callHandler接受数据

总结

主要介绍了原生应用嵌入网页(H5)与APP(android和ios)之间的通信实现方法。

这个通信过程主要依赖于 WebViewJavascriptBridge 这个桥接库。通过在JavaScript中调用native方法和native调用JavaScript方法,实现APP和H5的互通。

主要通过提供了 callHandlerregisterHandler 两个方法,分别用于在 JS 中调用 APP 端的方法和注册供 APP 端调用的 JS 方法。

参考资料:

ios-webview

android-webview

参考案例

相关推荐
轻口味33 分钟前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王1 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发1 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀2 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪2 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef4 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6414 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻4 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云5 小时前
npm淘宝镜像
前端·npm·node.js