问题产生原因:
前端与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 + ")");