客户端(安卓/ios)如何给前端对接
大致架构就是,原生客户端相当于一个壳,通过Webview嵌套着含有主要内容的H5,客户端对数据进行管理,如数据缓存或数据接口请求,然后将数据处理好传给前端,而前端主要是将数据以各种方式显示出来 。
WebViewJavascriptBridge is undefined,找不到Bridge对象
- 查找问题: 在Hybrid开发中,一般使用的是第三方的bridge通信库,这种库可以使原生和前端webview进行信息传递和方法的互调,采用的是JSBridge库,原生端会在webview的window对象中插入一个WebViewJavaScriptBridge对象,这个对象就是可以用call和register两大方法来和原生通信的关键对象。
- 解决过程分析: 排除手机系统问题,模拟器问题,XML布局问题等
- 最终解决方案: webViewClient也要设置成BridgeWebViewClient对象的overide!
js调用原生方法会偶现失败?
具体的表现: js调用native方法时shouldOverridgeUrlLoading没有被触发,因此端上没有去刷新JS调用的message queue.
JsBridge的异步不执行的处理--promise异步变同步
背景: 在进行后端接口请求的时候统一先把参数返给APP端,APP端进行加密以后,在返回给前端,前端再进行异步请求。 这里涉及到异步操作,异步请求可能会在和APP交互以前执行,那样就得不到APP返回的加密参数就执行了请求,因此得不到数据。 解决方案: 利用promise把APP,H5和后端之间的交互进行同步处理,一步一步进行交互操作。
- web端的bridge.js
var u = navigator.userAgent;
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
var isiOS = !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
// alert('是不是Android:'+isAndroid);
// alert('是不是iOS:'+isiOS);
function setupWebViewJavascriptBridge(callback) {
if(isAndroid){
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener('WebViewJavascriptBridgeReady', function (event) {
if(window.onWebViewJavascriptBridgeReady) window.onWebViewJavascriptBridgeReady(window.__bridge = WebViewJavascriptBridge);
callback(WebViewJavascriptBridge)
}, false)
}
}
if(isiOS){
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 = 'wvjbscheme://__BRIDGE_LOADED__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
}
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)
})
})
}
}
- 封装和APP交互的方法callBridge.js
export default {
methods:{
callBridgefn(json){ // 调用app加密方法
let p = new Promise((resolve, reject)=>{
this.$bridge.callhandler('encryptParams', JSON.stringify(json),(data) =>{ //encryptParams是APP端规定的方法名
resolve(data) })
}) return p;
},
goBack(){ // 调用APP的返回
this.$bridge.callhandler('goBack', (data) =>{ // goBack是APP端规定的方法名
})
}
}
}
- 利用promise重写axios异步请求方法promise.js
import axios from 'axios'
export default{
methods:{
sendServer(param) {
return new Promise((resolve,reject)=>{
axios.post(url ,param).then(res=>{ // url为请求地址
resolve(res.data)
}).catch(err=>{
reject(err)
})
})
},
}
}
- 在页面中请求接口的方法
_sendServer(param){
this.callBridgefn(param).then(data=>{
this.sendServer(JSON.parse(data))
.then(res=>{
// 这里写要对后端返回的数据进行的操做 }) })
}
- 在页面初始化的时候调用
created(){
this._sendServer(param) //param是要传递给APP进行加密的参数
}
JSBridge并发调用问题
问题: 同时并发发送多个请求,native端只能拦截到最后一次请求,前面的请求没法拦截。 改用location.href="scheme"这种方式是可以让native端都能拦截到,但是会产生内部webview后退时,请求不了native。 解决方法: 思路
- 假设JSBridge提供了方法call()
- 每次调用call时,会把当前所有的数据缓存在一个数组变量sendMessage里面
- 每次调用都会发送一个固定的scheme,
- native接受这个消息后,会调用js的一个固定全局方法pullMessage(),该方法返回值是sendMessage数组里面的所有数据的json数组字符串
- native拿到js方法返回的JSON数组字符串进行解析,然后针对每个调用进行分发处理,然后在进行回调相应的js方法。
项目问题
背景:app(A)页面跳转到h5(B)页面,然后H5(B)页面跳转到H5(C)页面,这时C页面无法调用app内的方法,但是在B页面是可以调用的。 思路: 让iOS调用我们的标识,然后在调用我们的方法,传参数过来,我们在对数据进行处理
$(documnet).ready(function(){
location.href ="aaaa://showMobile",// 一个标识
})
function jsonStr(str){
$('.lottery_content h5').html(str)
}