Android WebView、js互動方式原理總結
阿新 • • 發佈:2019-01-04
webView.loadUrl("javascript:console(" + "'Hello,China!'" + ")"");
二、js注入實現
先來說說原理吧,當js呼叫prompt()方法時,WebChromeClient.onJsPrompt()方法會被觸發,當js觸發Android提供的介面方法時,將該方法的方法名稱、引數型別、引數值轉成json,然後通過prompt方法傳遞給android端,android端解析json並通過反射執行對應的方法,同時也支援執行匿名回撥。 整個流程比較複雜,看圖:為WebView繫結WebChormeClient監聽,在Html載入進度25%時進行js注入(注入的js是根據android提供給js的物件類名動態生成); 動態注入的js程式碼如下:
程式碼不難,可以自行理解,其中回撥函式被封裝在了a物件裡面,確保android端可以通過webview.loadUrl()執行回撥。 android端回撥js程式碼如下:javascript: (function(b) { console.log("HostApp initialization begin"); var a = { queue: [], callback: function() { var d = Array.prototype.slice.call(arguments, 0);//獲取該函式引數並轉換為Array陣列 var c = d.shift();//取得陣列第一個元素 var e = d.shift(); this.queue[c].apply(this, d);//新建一個物件 屬性名稱為取得的c,並將d陣列作為他的值。然後將這個物件push到queue陣列 if(!e) {//e為空的時候,將queue陣列屬性名稱為c的物件刪除 delete this.queue[c] } } }; //各種賦值,最後都等於同一個函式 a.alert = a.alert = a.alert = a.delayJsCallBack = a.getIMSI = a.getOsSdk = a.goBack = a.overloadMethod = a.overloadMethod = a.passJson2Java = a.passLongType = a.retBackPassJson = a.retJavaObject = a.testLossTime = a.toast = 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 } } //將匿名物件{method: f.shift(),types: e,args: f}轉換成json字串並用瀏覽器彈出確認可輸入框,然後取得輸入框的值json序列化為js物件 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 }; //獲取a的屬性值,然後迴圈 Object.getOwnPropertyNames(a).forEach(function(d) { var c = a[d]; //判斷賦值 if(typeof c === "function" && d !== "callback") { a[d] = function() { //concat 連線兩個陣列 return c.apply(a, [d].concat(Array.prototype.slice.call(arguments, 0))) } } }); b.HostApp = a; console.log("HostApp initialization end") })(window);//閉包函式預設執行,然後賦給window。這樣window.b就可以執行了 b.HostApp就是執行a的內容,但是a具體處理邏輯不對外開放,避免外部汙染a內部邏輯
javascript:HostApp.callback(0, 0 ,"call back haha");
android提供的每一個js方法都對應一個JsCallback物件,android就可以通過JsCallback物件來生成並執行回撥js的程式碼。
三、優缺點
a.第一種方式不安全,不新增addJavascriptInterface,甚至預設false,在低於API17的WebView上預設新增"SearchBoxJavaBridge_"到mJavaScriptObjects中。這樣就有可能通過使用者信任的客戶端獲取SD卡的資料; b.第一種方式必須要API大於等於17才能使用 c.第一種方式當有js回撥函式需要android端執行時,都需要將匿名回撥函式賦值給全域性函式才能供android端回撥,增加了js和android端通訊的封裝層的低效程式碼量;而第二種方式則是通過動態注入js的方式則非常方便。 d.第二種方式也有一定限制,比如android提供的方法必須是static修飾的,且方法第一個引數必須為WebView,不過這不影響使用。最後,附上程式碼地址: 點我。