我们今天来介绍一款功能强大的 Android 与 Javascript 双向交互的开源库JsBridge
Android 要实现与 Javascript (以下简称 JS) 交互有以下几种常用方案:
- WebView addJavascriptInterface方法
- 拦截自定义链接实现数据交换
- 实现 prompt,console等原生方法来数据交互
方案一是官方推荐的,但是在 android 4.2以下存在安全漏洞,而且和 JS 交换的数据仅仅局限于基本类型(int,float,double,String)等,不支持 JS 函数回调。方案二是兼容 iOS 的方案, 一般情况下前端需要依赖 JS 文件, 交互的时候需要传递函数名, 参数和回调函数,传输数据长度就是 url 长度限制, 案例就是 lzyzsd / JsBridge 和 marcuswestin / WebViewJavascriptBridge, 方案三执行效率高,不限传输数据, 但也有弊端, 占据了系统函数,意味着前端不能再使用这个函数。
我们今天要介绍的库就是基于第三种方案的改进,基于 prompt 方法来实现交互。为什么说它功能强大呢?它可以实现你要想的任意 JS 方法,支持 JS 函数,对象,数组等所有基础类型的解析和回调。我们先来看个示例吧。
这是原生提供的一个分享方法
public class ServiceModule extends JsModule {
@Override
public String getModuleName() {
return "service";
}
@JSBridgeMethod
public void share(String msg, final JBCallback success, final JBCallback failure) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, msg);
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
getContext().startActivity(Intent.createChooser(intent, "share"));
success.apply("success");
} else {
failure.apply("failure");
}
}
JS 怎么调用呢?哇,一看就和其他妖艳** 不一样 
JsBridge.service.share('分享内容',
function(){
console.log('分享成功')
},
function(){
console.log('分享失败')
}
)
你说 JS 可能没有成功失败的回调?没关系,我们支持缺省参数,下面这样也可以哟,不过原生方法 share 收到的 JBCallback 参数就为空咯
JsBridge.service.share('分享内容');
数据还不够复杂?实际开发情况数据复杂多了。
那你看下面这样还行吗?JS 数组里基本包含了所有的类型
JsBridge.share.test(
[ - 1111111111111111111, 1.235, 'hello world', true,
function(args) {
alert(args)
},
{
a: 100101,
b: function() {
alert('执行复杂回调函数')
}
},
[1, 2, 3, 4]]);
原生怎么解析这种情况呢?so easy, 不就一个 JBArray嘛 
@JSBridgeMethod
public void test(JBArray array) {
for (int i = 0; i < array.size(); i++) {
String output = "" + array.get(i);
if (array.get(i) != null) {
output += "##" + array.get(i).getClass();
}
Log.d(JsBridge.TAG, output);
}
array.getCallback(4).apply("xxx");
array.getMap(5).getCallback("b").apply();
}
轻松回调 JS 数组里面的 function。JS 对象也不怕,JBMap全部搞定。
调用方法只能三个层级?我们项目不需要 module!!就想 JsBridge.test 直接调用。老铁当然没问题啦,只要继承JsStaticModule, 里面的方法分分钟变成静态,对象名直接调用。
public class ServiceModule extends JsStaticModule {
...
}
我们项目要求多个层级呢?
需求还真多,多个层级是需要多少层级呢?4级够了吗?不行再多点?那你自己按需求定制吧!!
public class ServiceModule extends JsModule {
@Override
public String getModuleName() {
return "a.b.c.d.e.f.g";
}
}
现在调用路径如下,
我不敢保证 FE 看到这个方法会不会拿刀去找你
JsBridge.a.b.c.d.e.f.g.xx(...);
嗯嗯,我已经直到这个库特别强大了,我们的 iOS 要实现类似功能怎么办?
我们推荐使用 marcuswestin / WebViewJavascriptBridge,JsBridge 是可以兼容这个库的。怎么兼容呢?iOS 的 WebViewJavascriptBridge不主要就是一个方法嘛?
bridge.registerHandler("getCurrentPageUrl", function(data,responseCallback) {
responseCallback(document.location.toString())
})
一个静态方法实习足以
怎么都觉得配合 iOS 这么强大的库就算杀鸡用牛刀了,欢迎有识之士开发 JsBridge 的 iOS 版本!
更多功能和介绍欢迎查看官方教程:github.com/pengwei1024…