問題產生原因:
前端與Android 交互時,調用Android 的方法,但是傳入的參數是function
例如:
這樣我們Android這邊接收不到值(我網上百度是沒找到好方法,有的說讓前端傳入jsonString給我們,能解決方法,但是前端要改動代碼)
解決思路:
我們加入一箇中間層,當js調用Android時,先調其他方法,使傳入值變成json在調用Android方法,這樣就可以接收了
實現方案:
注入js代碼,js不會寫,從別人借鑑過來的
jsString = "(function() {\n" +
" var PAG_NATIVE = window.PAG_NATIVE = {};\n" +
" PAG_NATIVE.callbacks = {};\n" +
" PAG_NATIVE.callBacks = {};\n" +
" PAG_NATIVE.exec = function(funName, args, callbackId) {\n" +
" var commend = {\n" +
" functionName: funName,\n" +
" arguments: args,\n" +
" callbackId: callbackId\n" +
" };\n" +
" window.android[funName](args);\n" + " };\n" +
" PAG_NATIVE.execCallBack = function(callbackId, res) {\n" +
" var callBack = PAG_NATIVE.callBacks[callbackId];\n" +
" if (callBack) {\n" +
" callBack(res);\n" +
" delete PAG_NATIVE.callBacks['callbackId'];\n" +
" }\n" +
" };\n" +
" PAG_NATIVE.openBluetoothAdapter = function(object) {\n" +
" var result = PAG_NATIVE.transformObject(object);\n" +
" PAG_NATIVE.exec('openBluetoothAdapter', result, \"\");\n" +
" };\n" +
"\n" +
" PAG_NATIVE.transformObject = function(object) {\n" +
" for (key in object) {\n" +
" if (typeof (object[key]) == 'function') {\n" +
" var identifier = (new Date()).getTime() + key;\n" +
" PAG_NATIVE.callbacks[identifier] = object[key];\n" +
" object[key] = identifier;\n" +
" }\n" +
" }\n" +
" return JSON.stringify(object);\n" +
" };\n" +
"\n" +
" PAG_NATIVE.commonCallback = function(object) {\n" +
" for (key in object) {\n" +
" if (typeof (PAG_NATIVE.callbacks[key]) == 'function') {\n" +
" PAG_NATIVE.callbacks[key](object[key]);\n" +
" PAG_NATIVE.callbacks['key'] = null;\n" +
" }\n" +
" }\n" +
"};\n" +
"})();";
注入調用
webview.loadUrl("javascript:"+NativeCommonJS.addJS());
時機是在webview onpagerFinish中調用,可以延遲1s加載,保證,網頁加載完畢
說明一下:利用集合記錄每一個的function,<k,v>,k是function加時間戳 ,v是原方法function,至於給方法加時間戳,是因爲,很多方法體可能同名:多個success。然後加入每調用增加一個方法,就要類似PAG_NATIVE.openBluetoothAdapter一樣,新增一個方法名,這個方法名是給前端js調用的,經過transformObject,將傳入值轉成了json,
,爲了區別我們調用的函數,最終調用Android的方法windrow.android[name](arg)
Android 這邊需要的操作
JSONObject jsonObject=new JSONObject(json);
String dara=jsonObject.getString("success");
//PAG_NATIVE.execCallBack
jsPost("PAG_NATIVE.commonCallback", "{'"+dara+"':12345" +"}");
//調用js方法
public void jsPost(final String method, final Object data) {
handler.post(new Runnable() {
@Override
public void run() {
webView.loadUrl("javascript:"+method+"(" + data + ")");
}
});
}
我用handle的原因是,子線程不能調用loadurl,可自行刪除
注意點:參數的拼接
"{'"+dara+"':12345" +"}"
1234可以直接放我們定義的對象,不需要tostring,js調用直接res.參數名
這是我目前的解決方法,感覺並不智能,也很繁瑣,只能解決特定的事,希望有好的思路可以留言
-------------------------------------
追記,上面實現了傳object,傳多個方法名的,但是一種特殊的,傳一個匿名方法funtcion,這個需要額外處理
前端js代碼
這個比傳object簡單,我們只要記住function名字就行了
js調Android中間轉換
" PAG_NATIVE.onBLECharacteristicValueChange = function(callback) {\n" + " PAG_NATIVE.callBacks['onBLECharacteristicValueChange'] = callback;\n" + " PAG_NATIVE.exec('onBLECharacteristicValueChange','{\"function\":\"onBLECharacteristicValueChange\"}', \"\");"+ " };"
android調js中間轉換
" PAG_NATIVE.execCallBack = function(callbackId, res) {\n" + " var callBack = PAG_NATIVE.callBacks[callbackId];\n" + " if (callBack) {\n" + " callBack(res);\n" + " delete PAG_NATIVE.callBacks['callbackId'];\n" + " }\n" + " };\n" +
java代碼
webView.loadUrl("javascript:" + testMethod2 + "('" + callback + "'," + data + ")");