Native/JS交互方案
标签(空格分隔): Hybird
1. 方案一 scheme拦截(JSBridge)
客户端通拦截H5的url,判定之后执行约定的逻辑。
1.1 使用方法
1.创建全局桥对象jsBridge。
2.js向native注册js方法。
Android:jsBridge.registerHandler(String funcName,Function func)
iOS :` [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
responseCallback(@"Response from testObjcCallback");
}];`
3.JS调用Native。
Android: jsBridge.callHandler(String funName,JSON data,Function callbackFunc)
iOS :` [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }];
4.native拦截调用
Android在
shouldOverrideUrlLoading中捕获url。iOS在
shouldStartLoadWithRequest中捕获url。
5.url的参数格式
需要解析api名、api使用的参数、回调函数id等。
6.native回调js的参数
封装成JSON格式回调,比如
{ "callbackKey": "key", "callbackData": "data" }
然后通过jsBridge通知H5页面回调。
7.Native调用js
jsBridge._handleMessageFromNative(JSON params)
通过JSON中的数据格式区分是回调还是主动调用。
- 比如主动调用就是
{ "handlerKey": "key", "handlerData": "data" } - 回调就是
{ "callbackKey": "key", "callbackData": "data" }
1.2 优点
- 兼容性好,适配各个系统版本,Android和iOS通用。
- 实现简单,容错率高。
- 兼容现有方案,需少量修改。
1.2 缺点
- 现存
flowpay和jsflowpay两套协议。 - 现存的native调用js方式需要修改(原为
loadUrl("javascript:params"))。
1.3 最终调用流程
2. 方案二 Native向JS注入对象
Native在适当的时机向浏览器注入jsInterface对象,所有通过此浏览器打开的网页均能使用该对象提供提供的native能力。
2.1 使用方法
1.鉴权并注入jsInterface对象。
webview.addJavascriptInterface(Object jsInterface,String objName);
2.js调用native能力。
window.jsInterface.xxx(params);
结果分文同步和异步返回。
2.1 同步返回可以直接拿到结果。`result=window.jsInterface.xxx(params);`
2.2 异步返回需要重新加载页面传入参数;或者调用约定好的js方法。
3.native调用js能力
- Android。
4.4版本之前用webview.loadUrl("javascript:(params)");。会刷新页面。无返回值,如果要求返回结果,需要H5页面异步回调。
4.4版本之后用webview.evaluateJavascript("javascript:params",Callback callback);。在callback中可以获取js的返回结果。
- iOS
WKWebview 使用
(void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler
结果异步返回,目前Stack Overflow上有使用category添加一个同步的返回函数,该函数就用while()不断的轮询,对UI界面有影响,有可能会卡住。
2.2 优点
- 使用简单。有业务变更时native端只负责提供能力。
2.3 缺点
- Android在4.2版本以下有webview远程执行js漏洞。可以参考这里。
- 在js里,两端的调用方式不同,需要区分。也可能是有统一的写法但我不知道。
3. 通过Webkit弹窗通知的回调实现交互
通过webChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt()消息
3.1 使用方法

1.js调用prompt方法
unction clickprompt(){
// 调用prompt()
var result=prompt("js://demo?params");
alert("demo " + result);
2.在客户端的WebChromeClient()重写onJsPrompt()
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// 根据协议的参数,判断是否是所需要的url
// 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
Uri uri = Uri.parse(message);
if (uri.getScheme().equals("js")) {
if (uri.getAuthority().equals("demo")) {
// 执行JS所需要调用的逻辑
System.out.println("js调用了Android的方法");
// 可以在协议上带有参数并传递到Android上
HashMap<String, String> params = new HashMap<>();
Set<String> collection = uri.getQueryParameterNames();
//参数result:代表消息框的返回值(输入值)
result.confirm("js调用了Android的方法成功啦");
}
return true;
}
return super.onJsPrompt(view, url, message, defaultValue, result);
}
3.2 优点
- 本质也是协议拦截,不存在兼容性问题。
3.3 缺点
- native层面与现有的协议不兼容,需要重做。
4. 总结

参考
Carson_Ho-最全面总结 Android WebView与 JS 的交互方式
不会写代码的IT男-WebView 安全之 addJavascriptInterface
lzyzsd-JsBridge