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'
这个的实现思路如下:
- 生成需要嵌入到html里面js代码
- 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 比较新