Android WebChromeClient下实现javaScript和Android互调
作者:陆金龙
发表时间:2024-02-25 04:55
关键词:
==========================1.js实现==========================
var nativeUtils={};
nativeUtils.CallBackMethods = new Hashtable();
//js调用本地函数
nativeUtils.invoke = function () {
var methodid = arguments[0] + (new Date()).getTime() + parseInt(Math.random() * 1000);
var nativearg = "native:" + arguments[0] + "@" + methodid + "(";
var arg = [];
for (var i = 1; i < arguments.length; i++) {//从1开始,因为0是要调用的
if (typeof (arguments[i]) == "function") {
this.CallBackMethods.add(methodid, arguments[i]);//缓存回调函数(键值对)
arg.push(methodid);//将回调函数替换成 与回调函数相关联的一个字符串值(缓存的键)
}
else {
arg.push(arguments[i]);//存放其他参数(回调函数外的)
}
}
nativearg += JSON.stringify(arg) + ")";//native:ScanCode@ScanCode147131232131207819("[\"扫一扫添加\",\"ScanCode147131232131207819\"]")
console.debug(nativearg);
}
//由本地回调js函数
nativeUtils.CallFromNative= function (methodid, args) {
var func = this.CallBackMethods.items(methodid);//存缓存取出函数
if (typeof (func) == "function") {
func.apply(func, args);
}
this.CallBackMethods.remove(methodid);//移除缓存
}
// 定义js函数来调用本地函数的
nativeUtils.ScanCode = function (title,callback) {
this.invoke("ScanCode",title,callback);
}
=========================2.Android实现===========================
public class MyBrowserClient extends WebChromeClient {
WebView webview;
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Pattern p = Pattern.compile("native:(.*?)@(.*?)\\((.*?)\\)");
Matcher matcher = p.matcher(msg);
if (matcher.matches())
{
String func = matcher.group(1);//本地方法名
String methodid = matcher.group(2);//回调函数名
String args = matcher.group(3);//调用本地方法的参数
CallNativeMethod(func,methodid,args);
}
return super.onConsoleMessage(consoleMessage);
}
//调用的实现
public static void CallNativeMethod(String func, String methodid ,String args )
{
MyJsInterface jsobj = (MyJsInterface) webview.GetJsInterface();
JSONArray array = new JSONArray();
try {
array = new JSONArray(args);//参数从json字符串还原
} catch (Exception err) {
err.printStackTrace();
}
Method[] methods = jsobj.getClass().getMethods();
for (Method m : methods) {
//检查是否有@JavascriptInterface标签
boolean isannotationed = false;
Annotation[] annotations = m.getDeclaredAnnotations();
for (Annotation a : annotations) {
if (a instanceof JavascriptInterface) {
isannotationed = true;
break;
}
}
if (!isannotationed) {
continue;
}
//查找到对应的方法
if (m.getName().equals(method)) {
Class[] argtypes = m.getParameterTypes();
if (array.length() == argtypes.length) //函数的参数个数必须一致
{
try {
List<Object> callargs = new ArrayList<Object>();
for (int i = 0; i < array.length(); i++) {//准备参数
if (array.get(i) == JSONObject.NULL) {
callargs.add(null);
} else {
callargs.add(array.get(i));
}
}
Object ret = m.invoke(jsobj, callargs.toArray());//调用本地方法
if (!m.getReturnType().equals(Void.TYPE)) {
RunPlatformCallBack(methodid, ret);//这里是有返回值立即回调,也可以后续需要时回调
}
} catch (Exception err) {
Log.e("CallNativeMethod", err.getMessage());
}
break;
}
}
}
}
//回调的实现
public static void RunPlatformCallBack(String func, Object args) {
String jsonStr = null;
if (args instanceof JSONArray || args instanceof JSONObject) {
jsonStr = args.toString();
} else {
JSONArray jsonobj = new JSONArray();
jsonobj.put(args);
jsonStr = jsonobj.toString();
}
String jsfunc = String.format("nativeUtils.CallFromNative('%s',%s)", func, jsonStr);
webview.loadUrl(String.format("javascript:%s", jsfunc));
}
=============================3.测试==============================
//测试调用
nativeUtils.ScanCode("扫一扫添加",function(scanedText){
alert("扫描到的文本:"+scanedText);
});