记录:离线包实现桥接

写在前面

  1. 使用 WebViewJavascriptBridge 框架,将WebViewJavascriptBridge对象由原生端注入到WebView中。
  2. 前端检验 window.WebViewJavascriptBridge 是否存在
  3. 通过特定机制(事件监听/iframe) 等待桥接准备就绪
  4. 使用原生注入的 WebViewJavascriptBridge 对象提供的方法:
    • callHandler: 调用原生功能
    • registerHandler: 注册供原生调用的方法

jsBridge编写

新建一个jsBridge文件

js 复制代码
const u = navigator.userAgent
const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1

/* eslint-disable */
function setupWebViewJavascriptBridge(callback) {
  // 第一次调用这个方法的时候,为false
  if (window.WebViewJavascriptBridge) {
    return callback(WebViewJavascriptBridge)
  }
  if (isAndroid) {
    document.addEventListener('WebViewJavascriptBridgeReady', function () {
      callback(WebViewJavascriptBridge)
    }, false)
  } else {
    // 第一次调用的时候,也是false
    if (window.WVJBCallbacks) {
      return window.WVJBCallbacks.push(callback)
    }
    // 把callback对象赋值给对象。
    window.WVJBCallbacks = [callback]
    // 这段代码的意思就是执行加载WebViewJavascriptBridge_JS.js中代码的作用
    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)
  }
}

/* Android 版本 WebViewJavascriptBridge 的设计要求:
通过调用 init() 方法,建立 JS 端与 Android 原生端的双向通信通道

iOS 版本的 WebViewJavascriptBridge 在桥接对象注入时自动完成初始化,
通过 iframe 机制触发加载后,桥接自动就绪 
*/
if (isAndroid) {
  setupWebViewJavascriptBridge(function (bridge) {
    bridge.init()
  })
}
export default {
  callhandler(name, data, callback) {
    setupWebViewJavascriptBridge(function (bridge) {
      bridge.callHandler(name, data, callback)
    })
  },
  registerhandler(name, callback) {
    setupWebViewJavascriptBridge(function (bridge) {
      bridge.registerHandler(name, function (data, responseCallback) {
        callback(data, responseCallback)
      })
    })
  }
}

Android

Android使用 addEventListener 的原因:

  • Android WebView 提供了标准的事件机制
  • 原生端可以在适当时候触发 JavaScript 事件
  • 通过 document.addEventListener 监听自定义事件是一种标准做法

Android原生端在初始化完成后主动触发 WebViewJavascriptBridgeReady 事件通知 JS 端

iOS

iOS 使用 iframe 的原因:

  • UIWebView(较老的 iOS WebView)没有像 Android 那样的直接事件触发机制
  • 但 WebView 会拦截特定 URL 请求,这是可以利用的特性

使用URL Scheme 拦截机制:

js 复制代码
var WVJBIframe = document.createElement('iframe') 
WVJBIframe.style.display = 'none' 
WVJBIframe.src = 'https://__bridge_loaded__' 
document.documentElement.appendChild(WVJBIframe)

创建一个隐藏的 iframe 并设置特殊 URL,iOS 原生端通过拦截这个 URL 请求来知道需要初始化桥接。

使用

index.js

js 复制代码
  import jsBridge from './jsBridge'
  
  /**
   * methods downloadImage  下载图片
   * params list {Array} base64列表parmas = {list: [base64]} base64不要前面的信息 img/png
   *        title {string}
   * */
    downloadImage  (params, responseCallback) {
        jsBridge.callhandler('downloadImage', params, (data) => {
          responseCallback(JSON.parse(data))
        })
    },
  
    /**
    * methods checkSmsCode 校验验证码
    * params businessCode  {string} (modifyDrawPasswordDynamic     銀行卡修改取款密碼
    * params strategyCode {string} (ebil_ebilling写死)
    * */
    checkSmsCode (params, responseCallback) {
        jsBridge.callhandler('checkSmsCode', params, (data) => {
          let obj = JSON.parse(data)
          if (obj.authStatus === 'pass') {
            responseCallback(JSON.parse(data))
          } else {
            Toast.info('驗證碼錯誤_SMS code Error')
          }
        })
   },
   
  /**
   * methods 校验账户的交易密码
   * params {} 无需传参
   * */
  getCheckPassword (responseCallback) {
    jsBridge.callhandler('getCheckPassword', {}, data => {
      if (data) {
        responseCallback(JSON.parse(data))
      }
    })
  },

前端页面:

js 复制代码
    getImg () {
      this.$bridge.downloadImage({ list: this.url }, () => {
        // console.log(res)
      })
    },
    nextPage () {
      this.$bridge.checkSmsCode({ businessCode: 'creditAutoAply', strategyCode: 'credit_aply_sms_code' }, res => {
        this.$bridge.getCheckPassword(data => {
          if (data.authStatus) {
            // 保存文件信息
            this.$remote(SAVE_FILE_INFO, params).then(res => {
              ....
            })
          }
        })
      })
    }

总结

  • Android: 利用标准事件机制,原生主动通知 Web
  • iOS: 利用 URL 拦截机制,Web 主动触发原生初始化
相关推荐
一 乐6 小时前
婚纱摄影网站|基于ssm + vue婚纱摄影网站系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端
C_心欲无痕6 小时前
ts - tsconfig.json配置讲解
linux·前端·ubuntu·typescript·json
清沫7 小时前
Claude Skills:Agent 能力扩展的新范式
前端·ai编程
yinuo7 小时前
前端跨页面通信终极指南:方案拆解、对比分析
前端
yinuo8 小时前
前端跨页面通讯终极指南⑨:IndexedDB 用法全解析
前端
xkxnq8 小时前
第二阶段:Vue 组件化开发(第 16天)
前端·javascript·vue.js
烛阴8 小时前
拒绝配置地狱!5 分钟搭建 Three.js + Parcel 完美开发环境
前端·webgl·three.js
xkxnq9 小时前
第一阶段:Vue 基础入门(第 15天)
前端·javascript·vue.js
anyup10 小时前
2026第一站:分享我在高德大赛现场学到的技术、产品与心得
前端·架构·harmonyos
BBBBBAAAAAi10 小时前
Claude Code安装记录
开发语言·前端·javascript