WebView与APP交互,即网页经过JSBrige
调用APP的功能,APP也能够经过JSBrige
调用网页提供的方法。最近恰好接触到这一块,记录一下前端侧的实际操做过程,这篇文章适合还没接触过这一块的同窗们,这里不讲原理,直接开始实战的过程。javascript
与客户端同窗沟通好使用的JSBrige库,我这里使用的是下面这两个库:前端
iOS(1.1w+ Star): https://github.com/marcuswestin/WebViewJavascriptBridgejava
Android(6k+ Star): https://github.com/lzyzsd/JsBridgeandroid
Star数量比较高,使用的企业也比较多,因此仍是比较可靠的,能够在它们的文档中示例代码。ios
注意: github上有不少这样的库,但最好配套使用,即iOS和Android注入的jsBrige名称一致,咱们前端使用时比较方便统一。
ios和android注入的jsbrige可能会有些差别,因此在使用前咱们须要抹平不一样客户端的差别。
若是app的同窗使用了上面说的库,安卓和iOS会在WebView中的window下注入一个WebViewJavascriptBridge
的对象,iOS有多是注入WVJBCallbacks
的数组,也有可能须要经过iframe
来注入。iOS的文档中给出了一个兼容的示例代码:git
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下:github
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交互的桥梁。数组
APP端的同窗须要先用库提供的方法在APP端实现一个方法,方法名好比:playMusic(musicId)
,能够传递参数musicId
,表示让APP开始播放某一首音乐。js调用时如:app
window.setupWebViewJavascriptBridge(function (bridge) { bridge.callHandler('playMusic', { musicId: 1 }, function (data) { console.log('app触发成功了,音乐正在播放。。。APP回调返回的数据:', data) }) })
上面至关于向app发起了一个playMusic
请求,app收到请求后,执行相关的动做,而后能够callback
,网页能够拿到回调并继续作相关动做(须要的话)。函数
一样的道理,若想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的交互其实就完成了,就是这么简单。
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)
这坨代码写的很挫,让我尴尬癌都犯了,有没有热心的小伙伴帮我优化下写法[送花花]。
callback
回调不成功,js收不到app返回的消息这个问题其实github上有issue,这是安卓1.0.4版本没有解决的问题,最新的代码已经解决了。解决办法是:安卓须要引入最新的master的代码,而不要使用1.0.4版本的代码。