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端:

    1. 调用对应方法:
<html>
    <script language="javascript">
      var msg="I' a msg from js";
    </script>
    <body>
      <button onclick='Giraffe.showToast(msg)'>Show Toast</button>
      <br/>
    </body>
</html>

局限性

  1. 在4.2之前的系统上存在安全问题:被注册的JavascriptInterface对象所有公共方法都可以被访问到;
  2. 在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可以在WebViewClientshouldOverrideUrlLoading方法中拿到相应的链接回调。

shouldOverrideUrlLoading方法中,除了可以像方法二中识别出的JSBridge协议进行处理, 在执行loadUrl操作之前,建议对相应的链接进行安全校验和检查。

另外, 实践过程中业务方在Web端的链接调用方式千奇百怪,有几种调用问题需要注意一下:

  • iframe + target="_blank"的调用方式无法回调到shouldOverrideUrlLoading方法。
  • 当客户端支持了多窗口模式setSupportMultipleWindows后, 对于target="_blank"的情况,如果链接是一个非网络urlshouldOverrideUrlLoading方法有可能不会被回调到。 如果需要,可以在onCreateWindow方法里面拦截处理。

个人觉得target="_blank这种情况对于客户端是个伪需求, 因为移动端的页面栈是自己来管理的,通常并不会新开一个页面来加载Web页面,而是在当前页面处理; 而对于PC端而言,JSBridge协议本身又不会生效。 因此对于此种case,统一收口在shouldOverrideUrlLoading方法里面处理即可。