在Android中可能因为业务场景需要,JS需要调用Native业务逻辑代码,Native需要通知JS,也即需要实现JS和Native之间通信;
Java通知JS方式:
WebView.load("javascrpt:method("+param+");");
JS通知Java有如下几种方式
1、addJavascriptInterface
具体使用示例参见官网描述
但该方案存在版本兼容问题,在4.2版本以下系统上存在安全漏洞,JS能够根据反射能访问注入的对象公有域。当WebView包含恶意代码时,攻击者可以以意想不到的方式来控制宿主App,使用这种方式需要特别小心。一般不建议使用此种方式
不能翻墙的可以看看这个
2、onJsPrompt
我们可以通过onJsPrompt这种方式来实现JS和Native之间交互。
每当JS调用prompt方法时Native的WebView所绑定的WebChromeClient的onJsPrompt方法会被触发
我们看看官方的说明
大意是告诉Client去显示一个提示框。如果返回true,WebView就会认为Client将要处理dialog并调用JsPromptResult合适方法(confirm/cancel)通知WebView;如果返回false,默认值将被返回给JS;方法默认返回false。
JS在调用prompt(message, defaultValue)方法时会传递2个参数给Native,分别对应onJSPrompt的第二、三个参数
我们只要和JS那边达成一套协议
myschem://className/methodName?data={param:xxx,callback:xxx}
className: JS调用Native的全路径名
methodName: JS调用Native具体方法
param: Native类方法名的入参
callback: Native调用JS的方法
Native从onJsPrompt方法接受到的message参数符合上面格式后,就可以知道调用Native哪个类哪个方法并且可以将Native产生的数据通过callback方式通知给JS,这是目前Native和JS之间交互的主流的通信方式。
示例代码:
@Override
public boolean onJsPrompt(final WebView view, String url, final String message,
String defaultValue, final JsPromptResult result) {
//parse message
boolean isLegal = isLegal(message);
if (isLegal) {
//invoke Native method
//notice js result
WebView.load("javascrpt:${callback}("+${param}+");");
result.confirm("lightweight data");
} else {
result.confirm();
}
return true;
}
注意事项
- 返回值**必须**true,如果返回false,WebView会弹一个很丑的对话框,阻塞用户体验
- 在返回前必须调用confirm方法
- 传递给confirm的值必须是轻量级的数据
- onJsPrompt方法运行在WebView创建的线程中(一般是UI线程)
- onJsPrompt的操作不要过重
- 在Activity销毁时避免JS的调用
3、H5白屏的问题解决方式
- 如果JS和Native交互使用到onJsprompt方式请确保遵循上面注意事项
- 因为JavaScript是单线程,如果上面方式还是解决不了白屏问题,请让H5同学使其JS调用放到后台线程