用WebViewJavascriptBridge进行JS和app进行交互
场景描述做项目的时候有一个业务是需要前端web给安卓发送指令,进行拍照个读取身份证的操作,这个时候是需要用户进入页面的时候直接进行的操作,那么这个时候我需要做的是告诉安卓什么时候调取什么样子的硬件,那么我们难题就是js和安卓怎么进行通信,有这样的需求也是很少见的,但是既然存在这样的需求还是需要进行解决的,那么我参考的是这个地址的方案:JsBridgevue调用的问题这个直接原生js写是没有...
场景描述
做项目的时候有一个业务是需要前端web给安卓发送指令,进行拍照个读取身份证的操作,这个时候是需要用户进入页面的时候直接进行的操作,那么这个时候我需要做的是告诉安卓什么时候调取什么样子的硬件,那么我们难题就是js和安卓怎么进行通信,有这样的需求也是很少见的,但是既然存在这样的需求还是需要进行解决的,那么我参考的是这个地址的方案:
JsBridge
vue调用的问题
这个直接原生js写是没有问题的,但是vue直接调用的时候一直不成功,也就是我直接可以发送指令过去,但是安卓返回的结果我一直拿不到,问题不知道出现在哪里,这个例子我这里不贴出来了,代码还是挺长的加上我自己的逻辑,直接看上面的链接,里面的demo是有完整的例子的,直接运行demo是没有问题,但是我将代码仍到vue里面的时候直接出现了问题,最后改了写法,可以了,哦,这里抛出一个问题,就是一样的的项目,win下启动没有问题,我用mac启动的时候就一直报错,这个问题谁遇到过,可以联系我一下,万分感谢!
问题解决
第一步 在src下新建一个bridgejs
觉得不规范的话,可以外面包括一个文件夹。
function setupWebViewJavascriptBridge (callback) {
if (window.WebViewJavascriptBridge) {
return callback(window.WebViewJavascriptBridge)
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback)
}
window.WVJBCallbacks = [callback]
let WVJBIframe = document.createElement('iframe')
WVJBIframe.style.display = 'none'
WVJBIframe.src = 'https://__bridge_loaded__'
document.documentElement.appendChild(WVJBIframe)
setTimeout(() => {
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)
})
})
}
}
直接复制到js里面
第二步:在main.js里面引入
import Bridge from './config/bridge.js'
Vue.prototype.$bridge = Bridge
第三步:在使用的页面直接发送指令
//app返回的数据
//functionInJs 后端的回调函数名字
that.$bridge.registerhandler('functionInJs', (data, responseCallback) => { //data 就是app返回的数据
responseCallback(data);
});
//给app传数据 card是标示 这里是前后端约定好的。
//submitFromWeb 我们回调的函数
that.$bridge.callhandler('submitFromWeb',card, (data) => {
// 处理返回数据 发送读取身份证读卡器的指令
if(data === 'true'){
//判断interval 循环是否存在,存在的话直接将计时器删除
that.hintInfo('success',data);
}else{
setTimeout(that.Get_card_info,3000);
that.hintInfo('warning','请调整身份证摆放位置!');
}
})
这样直接写是可以的,但是好像还是需要这行文件的, 我的是用到了,我第一次使用不确定是不是一定需要下面这个文件,但是如果你们失败了可以直接加上这个文件:
WebViewJavascriptBridge.js
//notation: js file can only use this kind of comments
//since comments will cause error when use in webview.loadurl,
//comments will be remove by java use regexp
(function() {
if (window.WebViewJavascriptBridge) {
return;
}
var messagingIframe;
var sendMessageQueue = [];
var receiveMessageQueue = [];
var messageHandlers = {};
var CUSTOM_PROTOCOL_SCHEME = 'yy';
var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';
var responseCallbacks = {};
var uniqueId = 1;
function _createQueueReadyIframe(doc) {
messagingIframe = doc.createElement('iframe');
messagingIframe.style.display = 'none';
doc.documentElement.appendChild(messagingIframe);
}
//set default messageHandler
function init(messageHandler) {
if (WebViewJavascriptBridge._messageHandler) {
throw new Error('WebViewJavascriptBridge.init called twice');
}
WebViewJavascriptBridge._messageHandler = messageHandler;
var receivedMessages = receiveMessageQueue;
receiveMessageQueue = null;
for (var i = 0; i < receivedMessages.length; i++) {
_dispatchMessageFromNative(receivedMessages[i]);
}
}
function send(data, responseCallback) {
_doSend({
data: data
}, responseCallback);
}
function registerHandler(handlerName, handler) {
messageHandlers[handlerName] = handler;
}
function callHandler(handlerName, data, responseCallback) {
_doSend({
handlerName: handlerName,
data: data
}, responseCallback);
}
//sendMessage add message, 触发native处理 sendMessage
function _doSend(message, responseCallback) {
if (responseCallback) {
var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();
responseCallbacks[callbackId] = responseCallback;
message.callbackId = callbackId;
}
sendMessageQueue.push(message);
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;
}
// 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容
function _fetchQueue() {
var messageQueueString = JSON.stringify(sendMessageQueue);
sendMessageQueue = [];
//android can't read directly the return data, so we can reload iframe src to communicate with java
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);
}
//提供给native使用,
function _dispatchMessageFromNative(messageJSON) {
setTimeout(function() {
var message = JSON.parse(messageJSON);
var responseCallback;
//java call finished, now need to call js callback function
if (message.responseId) {
responseCallback = responseCallbacks[message.responseId];
if (!responseCallback) {
return;
}
responseCallback(message.responseData);
delete responseCallbacks[message.responseId];
} else {
//直接发送
if (message.callbackId) {
var callbackResponseId = message.callbackId;
responseCallback = function(responseData) {
_doSend({
responseId: callbackResponseId,
responseData: responseData
});
};
}
var handler = WebViewJavascriptBridge._messageHandler;
if (message.handlerName) {
handler = messageHandlers[message.handlerName];
}
//查找指定handler
try {
handler(message.data, responseCallback);
} catch (exception) {
if (typeof console != 'undefined') {
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);
}
}
}
});
}
//提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以
function _handleMessageFromNative(messageJSON) {
console.log(messageJSON);
if (receiveMessageQueue && receiveMessageQueue.length > 0) {
receiveMessageQueue.push(messageJSON);
} else {
_dispatchMessageFromNative(messageJSON);
}
}
var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {
init: init,
send: send,
registerHandler: registerHandler,
callHandler: callHandler,
_fetchQueue: _fetchQueue,
_handleMessageFromNative: _handleMessageFromNative
};
var doc = document;
_createQueueReadyIframe(doc);
var readyEvent = doc.createEvent('Events');
readyEvent.initEvent('WebViewJavascriptBridgeReady');
readyEvent.bridge = WebViewJavascriptBridge;
doc.dispatchEvent(readyEvent);
})();
下面是我们的文件结构:
WebViewJavascriptBridge原理图
附带几个写得好的交互的例子
https://www.jianshu.com/p/d12ec047ce52
https://www.cnblogs.com/yongbufangqi1988/p/8462275.html
PS:这个js不确定是不是一定需要的,如果成功了这个就不用加, 以后我玩的熟了,我会继续更新这个,写的再详细一点,目前可以确定的是如果这个WebViewJavascriptBridge.js不加可能成功,但是如果加上一定是成功的!
谢谢阅读!
更多推荐
所有评论(0)