前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用WebViewJavascriptBridge进行JS和app进行交互

用WebViewJavascriptBridge进行JS和app进行交互

作者头像
何处锦绣不灰堆
发布2020-05-28 23:03:49
3.1K0
发布2020-05-28 23:03:49
举报
文章被收录于专栏:农历七月廿一农历七月廿一
场景描述

做项目的时候有一个业务是需要前端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不加可能成功,但是如果加上一定是成功的! 谢谢阅读!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-07-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景描述
  • vue调用的问题
  • 问题解决
    • 第一步 在src下新建一个bridgejs
      • 第二步:在main.js里面引入
        • 第三步:在使用的页面直接发送指令
          • WebViewJavascriptBridge原理图
            • 附带几个写得好的交互的例子
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档