WebView与APP交互实战纪录

WebView与APP交互

WebView与APP交互,即网页经由历程JSBrige挪用APP的功用,APP也能够经由历程JSBrige挪用网页供应的要领。近来恰好打仗到这一块,纪录一下前端侧的现实操作历程,这篇文章合适还没打仗过这一块的同砚们,这里不讲原理,直接最先实战的历程。

准备工作

与客户端同砚沟通好运用的JSBrige库,我这里运用的是下面这两个库:

iOS(1.1w+ Star): https://github.com/marcuswestin/WebViewJavascriptBridge

Android(6k+ Star): https://github.com/lzyzsd/JsBridge

Star数目比较高,运用的企业也比较多,所以照样比较牢靠的,能够在它们的文档中示例代码。

注重: github上有许多如许的库,但最好配套运用,即iOS和Android注入的jsBrige称号一致,我们前端运用时比较轻易一致。

开辟步骤

1. 一致封装APP注入的JSBrige

ios和android注入的jsbrige能够会有些差别,所以在运用前我们须要抹平差别客户端的差别。
假如app的同砚运用了上面说的库,安卓和iOS会在WebView中的window下注入一个WebViewJavascriptBridge的对象,iOS有多是注入WVJBCallbacks的数组,也有能够须要经由历程iframe来注入。iOS的文档中给出了一个兼容的示例代码:

function setupWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
    if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
    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)
}

我们能够直接运用上面的代码,为了运用轻易,在页面onload后,我们将这个函数挂在window下:

window.onload = function () {
  function setupWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
    if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
    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)
  }
  window.setupWebViewJavascriptBridge = setupWebViewJavascriptBridge
}

window.setupWebViewJavascriptBridge这个函数,就是我们所说的JSBridge,即WebView与APP交互的桥梁。

2. JS挪用APP的要领

APP端的同砚须要先用库供应的要领在APP端完成一个要领,要领名比方:playMusic(musicId),能够通报参数musicId,示意让APP最先播放某一首音乐。js挪用时如:

window.setupWebViewJavascriptBridge(function (bridge) {
        bridge.callHandler('playMusic', { musicId: 1 }, function (data) {
          console.log('app触发胜利了,音乐正在播放。。。APP回调返回的数据:', data)
        })
      })

上面相当于向app发起了一个playMusic要求,app收到要求后,实行相干的行动,然后能够callback,网页能够拿到回调并继承做相干行动(须要的话)。

3. APP调JS供应的要领

一样的原理,若想APP能挪用JS供应的要领,JS中要先注册这个要领,要领名比方stateChange(state),JS注册要领:

window.setupWebViewJavascriptBridge(function (bridge) {
  bridge.registerHandler('stateChange', function (data, responseCallback) {
    console.log('收到APP要求stateChange事宜,要求的数据是:', data)
    // 能够返回给app一个回调
    responseCallback('朕已收到APP爱卿的要求了,且退下!')
  })
})

到这里,WebView与app的交互实在就完成了,就是这么简朴。

注重事项

1. window.onload时就callHandler能够不胜利

平常在Android中会涌现这个题目,这是由于APP注入的WebViewJavascriptBridge还不存在,JS就挪用个中的要领了,所以就会没有结果。而Android的库也给出了这个注重事项,所以得如许写:

window.onload = function () {
  function registerAppEvent () {
    window.setupWebViewJavascriptBridge(function (bridge) {
      bridge.registerHandler('stateChange', function (data, responseCallback) {
        console.log('收到APP要求,要求的数据是:', data)
        // 能够返回给app一个回调
        responseCallback('朕已收到APP爱卿的要求了,且退下!')
      })
    })
  }

  // 兼容写法 
  if (window.WebViewJavascriptBridge) {
    registerAppEvent()
  } else {
    document.addEventListener(
        'WebViewJavascriptBridgeReady'
        , function() {
            registerAppEvent()
        },
        false
    )
  }
}

但这里没有考虑到iOS的状况,在最新的iOS中WebViewJavascriptBridge多是不存在的,所以上面写法registerAppEvent()在iOS能够没法实行。为了防止屡次注入事宜,我这里用了setTimeout,兼容两头的流程:

  let isInitBridgeEvent = false // 作为是不是已注册过事宜的标记
  if (window.WebViewJavascriptBridge) {
    registerAppEvent()
    isInitBridgeEvent = true
  } else {
    document.addEventListener(
      'WebViewJavascriptBridgeReady',
      function () {
        registerAppEvent()
        isInitBridgeEvent = true
      },
      false
    )
    // 假如还没注册则再注册一次
    setTimeout(() => {
      if (!isInitBridgeEvent) {
        registerAppEvent()
        isInitBridgeEvent = true
      }
    }, 100)

这坨代码写的很挫,让我为难癌都犯了,有无热情的小伙伴帮我优化下写法[送花花]。

2. js挪用安卓后callback回调不胜利,js收不到app返回的音讯

这个题目实在github上有issue,这是安卓1.0.4版本没有处理的题目,最新的代码已处理了。
处理办法是:安卓须要引入最新的master的代码,而不要运用1.0.4版本的代码。

    原文作者:fengxianqi
    原文地址: https://segmentfault.com/a/1190000018208609
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞