js bridge 原理

464 阅读1分钟

webview

webview 是安卓的一个视图组件,它基于webkit内核,相当于一个内置的浏览器,它的功能就是显示网页;

webview 调用java方法

  • 允许webview加载js;
  • 编写js接口类;
  • 给webview添加js接口;
...
initWidgets(savedInstanceState);
private void initWidgets() {
    mWebview = findViewById(R.id.webview);
    // 允许webview加载js代码
    mWebview.getSettings().setJavaScriptEnabled(true)
    // 给webview添加js接口
    mWebview.addJavaScriptInterface(new demoJsInterface(),name: "demodemo")
}
//  编写js接口类
public class demoJsInterface() {
    private static final String TAG = 'demoJsInterface'
    @JavaScriptInterface
    public void setValue(String vavlue) {
        Log.d(TAG, msg: "value=" + value)
    }
}

JSbridge 在Vue的封装与交互

jsbridge.js

let isAndroid = navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Adr') > -1;
let isIos = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
function setupWebViewJavascriptBridge(callback) {
    // android
    if (isAndroid) {
        if (window.WebViewJavascriptBridge) {
            callback(WebViewJavascriptBridge)
        } else {
            document.addEventListener(
                'WebViewJavascriptBridgeReady',
                function () {
                    callback(WebViewJavascriptBridge)
                },
                false
            );
        }
        sessionStorage.phoneType = 'android'
    }
    //ios
    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);
        sessionStorage.phoneType = 'ios'
    }
}
//注册回调函数,第一次连接时调用 初始化函数(android需要初始化,ios不用)
setupWebViewJavascriptBridge(function (bridge) {
    if (isAndroid) {
        //初始化
        bridge.init(function (message, responseCallback) {
            var data = {
                'Javascript Responds': 'Wee!'
            };
            responseCallback(data);
        })
    }
})
export default {
    // js调APP方法 (参数分别为:app提供的方法名  传给app的数据  回调)
    callHandler(name, data, callback) {
        setupWebViewJavascriptBridge(function (bridge) {
            bridge.callHandler(name, data, callback)
        })
    },
    // APP调js方法 (参数分别为:js提供的方法名  回调)
    registerHandler(name, callback) {
        setupWebViewJavascriptBridge(function (bridge) {
            bridge.registerHandler(name, function (data, responseCallback) {
                callback(data, responseCallback)
            })
        })
    }
}
-----------------------------
main.js中引入:
import Bridge from './JSbridge.js'
Vue.prototype.$bridge = Bridge
------------------------------
// js调app
  sendMsg(){
    let msg = this.msg
    this.$bridge.callHandler('dataToAndroid',msg,(res)=>{
      alert('获取app响应数据:'+res)
      this.test = res
    })
  },
 
// app调js
  getAPPDate(){
    this.$bridge.registerHandler('dataToJs', (data, responseCallback) => {
      alert('app主动调用js方法,传入数据:'+ data)
      responseCallback(data)
    })
  }

jsbridge调用本地方法,h5监测到调用,判断方法是否可以调用,可以调用的话,h5页面通过jsbridge对象触发一个url scheme,原生捕获,分析scheme知道了调用哪种方法,知道回调函数id;执行原生方法,调用jsbridge回调函数的id和参数;