Web端调用客户端方法
通常情况下, Web端都是作为业务方存在,通过webview作为桥梁与客户端进行交互。 在Web端调用Native接口的方法主要有以下三种途径:
- 注册
JavascriptInterface
对象 - 通过alert,confirm,以及prompt方法传值到Native层
- Native拦截url请求获取到JS所传递的数据
JavascriptInterface
对象
方法一 :注册Native端:
- Step1. 实现可供调用的JavascriptInterface
public class GiraffeJSInterface {
@JavascriptInterface
public void showToast(String msg) {
// ...
}
}
- Step2. 开启JS功能并注册JavascriptInterface
webSetting.setJavaScriptEnabled(true);
mWebview.addJavascriptInterface(new GiraffeJSInterface(this),"Giraffe");
- Step3. 加载H5页面
mWebview.loadUrl(mUrl);
Web端:
- 调用对应方法:
<html>
<script language="javascript">
var msg="I' a msg from js";
</script>
<body>
<button onclick='Giraffe.showToast(msg)'>Show Toast</button>
<br/>
</body>
</html>
局限性
- 在4.2之前的系统上存在安全问题:被注册的JavascriptInterface对象所有公共方法都可以被访问到;
- 在4.2以后,只有通过
@JavascriptInterface
注解的公共方法才能被调用。
方法二 :拦截prompt方法传值到Native层
当Web端调用alert,confirm,以及prompt方法的弹框时,客户端可以在对应的回调方法中拦截到相应的调用信息,从而获取到传递相应数据到Native并唤起相应的功能和服务。
通常情况下,考虑到返回值的灵活性,客户端通常选择覆写WebChromeClient
中的onJsPrompt
回调方法,对prompt方法调用拦截,并根据相应的JSBridge
协议进行处理。
然而有些问题需要我们注意下, 通常情况下我们认为onJSprompt方法中不会对参数长度进行限制,但在实际业务开发中业务方传递了什么却无法控制。 见过一些异常的Case, 某些机型和系统对传递过来的超长url进行了截断, 出现非常诡异的Bug, 因此不建议业务方夹杂过多无用参数在url中。
方法三 :通过拦截url请求获取到JS所传递的数据
当Web端通过<a href=“xxxx”>
标签进行页面跳转请求的时候,通常情况下都会回调给客户端, Android可以在WebViewClient
的shouldOverrideUrlLoading
方法中拿到相应的链接回调。
在shouldOverrideUrlLoading
方法中,除了可以像方法二
中识别出的JSBridge
协议进行处理, 在执行loadUrl
操作之前,建议对相应的链接进行安全校验和检查。
另外, 实践过程中业务方在Web端的链接调用方式千奇百怪,有几种调用问题需要注意一下:
iframe + target="_blank"
的调用方式无法回调到shouldOverrideUrlLoading
方法。- 当客户端支持了多窗口模式
setSupportMultipleWindows
后, 对于target="_blank"
的情况,如果链接是一个非网络url
,shouldOverrideUrlLoading
方法有可能不会被回调到。 如果需要,可以在onCreateWindow
方法里面拦截处理。
个人觉得target="_blank
这种情况对于客户端是个伪需求, 因为移动端的页面栈是自己来管理的,通常并不会新开一个页面来加载Web页面,而是在当前页面处理; 而对于PC端而言,JSBridge
协议本身又不会生效。
因此对于此种case,统一收口在shouldOverrideUrlLoading
方法里面处理即可。