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

参考案例

相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me7 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者7 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架
qq_392794488 小时前
前端缓存策略:强缓存与协商缓存深度剖析
前端·缓存