h5與native互動總結1

xingstarx發表於2018-01-18

1. 常見的通訊方案

在這裡我們討論的是Android平臺,js與native通訊主要包括Java調Js,Js調Java; Java調Js主要是通過webView.loadUrl(url)來實現,Js調Java包括兩種;一種是Android原生支援的addJavascriptInterface(),另一種就是JsBridge.

2. jsBridge

這裡我們主要討論的是jsBridge,jsBridge不同的開源專案實現的方式還是有些細微的差別的

3. safe-java-js-webview-bridge

這個方案存在很早了,但是作者已經很久都沒有維護了,還是有不少缺陷的,我更新了工程的配置,重新做了下處理。 使用的時候只需要依賴

compile 'com.github.xingstarx:safe-java-js-webview-bridge:master-SNAPSHOT'
複製程式碼

這個的實現思路如下:

  1. 生成需要嵌入到html裡面js程式碼
  2. js呼叫Java方法的時候會回撥WebChromeClient的onJsPrompt方法,這個時候會把關鍵的引數資訊傳遞回來,對這些引數進行解析並執行,也就是執行jsCallJava.call(webView, jsonStr),在這個過程中,就通過反射的機制,執行了我們的java方法

貼一下格式化後的這段js程式碼:

javascript: (function(b) {
    console.log("HostApp initialization begin");
    var a = {
        queue: [],
        callback: function() {
            var d = Array.prototype.slice.call(arguments, 0);
            var c = d.shift();
            var e = d.shift();
            this.queue[c].apply(this, d);
            if (!e) {
                delete this.queue[c]
            }
        }
    };
    a.alert = a.changeVariables = a.retJavaObject = a.selectImage = a.toast = function() {
        var f = Array.prototype.slice.call(arguments, 0);
        if (f.length < 1) {
            throw "HostApp call error, message:miss method name"
        }
        var e = [];
        for (var h = 1; h < f.length; h++) {
            var c = f[h];
            var j = typeof c;
            e[e.length] = j;
            if (j == "function") {
                var d = a.queue.length;
                a.queue[d] = c;
                f[h] = d
            }
        }
        var g = JSON.parse(prompt(JSON.stringify({
            method: f.shift(),
            types: e,
            args: f
        })));
        if (g.code != 200) {
            throw "HostApp call error, code:" + g.code + ", message:" + g.result
        }
        return g.result
    };
    Object.getOwnPropertyNames(a).forEach(function(d) {
        var c = a[d];
        if (typeof c === "function" && d !== "callback") {
            a[d] = function() {
                return c.apply(a, [d].concat(Array.prototype.slice.call(arguments, 0)))
            }
        }
    });
    b.HostApp = a;
    console.log("HostApp initialization end")
})(window);
複製程式碼

js學的不是很好,這段程式碼沒看懂,好菜啊?

4. 存在的缺陷,以及完善,對koltin的支援

github上面這個專案的issue不少,作者也沒有在跟進了,問題比較多 另外專案用上了如今比較火的kotlin語言,那麼實現的HostApp這個kotlin類無法正常工作,是由於koltin的語言特性造成,kotlin實現的類預設都是public final method()形式的

if (method.getModifiers() != (Modifier.PUBLIC | Modifier.STATIC) || (sign = genJavaMethodSign(method)) == null) {
                    continue;
                }
複製程式碼

JsCallJava的構造方法裡面有這麼一段判斷邏輯,規定了HostApp裡面的類方法得是public static method(),而不能是其他的,所以對判斷邏輯做了一點修改

//針對kotlin語言做相容處理,kotlin實現的HostApp,是`pubic static final method()`,而java語言實現的HostApp是`public static method()`,仔細理解下面的位運算
if ((method.getModifiers() | Modifier.FINAL) != (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL) || (sign = genJavaMethodSign(method)) == null) {
        continue;
  }
複製程式碼

5. 其他的jsBridge方案

在github上找到了其他的jsBridge,還需要調研下在總結 JsBridge 有一段時間沒有維護了 JsBridge 比較新

相關文章