美文网首页
JSBridge小科普

JSBridge小科普

作者: 娜姐聊前端 | 来源:发表于2020-07-15 00:49 被阅读0次

    做Hybird APP开发的同学,应该对JSBridge不陌生,它用于H5页面和Native(Android或者iOS)通信。常用的三方库如Dsbridge系列(https://github.com/wendux/DSBridge-Android)。那么,你知道JSBridge到底是如何在两端进行通信的吗?

    下面的实例代码,Native端以Android为例。

    1. Web调用Native能力

    1.1 通过URI Schema请求(全局注册)

    Native应用可以在移动端系统中注册一个Schema协议的URI,这个URI可以在系统的任意地方授权访问,用来调起一段原生方法,或者唤起一个原生界面。

    于是,Native WebView控件中的H5页面,可以通过JS代码请求这个通用Schema协议。
    比如,通过添加一个不可见的iframe,设置其src属性,发送一个URI请求。

    let iframe = document.createElement('iframe');
    iframe.setAttribute('style', 'display:none');
    document.body.appendChild(iframe);
    iframe.setAttribute('src', 'myapp://className/method?args')
    

    整个调用流程如下图。一旦系统捕获到注册表中的Schema URI,就会通过此URI地址执行该Schema协议定义的Native操作,执行一段Native代码或者打开APP的某个页面(如打开摄像头,唤起图片预览功能,跳转APP支付页面等)

    jsBridge_native Schema.png
    1.2 通过代码注入(针对webView组件)

    以Android为例,可以通过addJavascriptInterface方法将Native的一个对象注入到页面中,供JS调用。

    /** 
    * 添加javascriptInterface 
    * 第一个参数:这里需要一个与js映射的java对象 
    * 第二个参数:该java对象被映射为js对象后在js里面的对象名,在js中要调用该对象的方法就是通过这个来调用 
    */  
     webView.addJavascriptInterface(new JSInterface(), "android");  
    
     private final class JSInterface{  
        /** 
         * 注意这里的@JavascriptInterface注解, target是4.2以上都需要添加这个注解,否则无法调用 
         * @param text 
         */  
        @JavascriptInterface  
        public void showToast(String text){  
             Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();  
        }  
    }  
    --------------------------------------------------------------------
    /**
     * js中调用java方法
     */
    android.showToast('toast');
    

    Native会向webView全局作用域注入一个android的全局对象,该对象上有showToast的方法。

    Android 4.2 之前注入对象的接口是 addJavascriptInterface ,但是由于安全原因慢慢不被使用(4.2以下版本,通过JS可以访问设备SD卡上面的任何内容,甚至是联系人信息,短信等。此为安全漏洞)。

    现在,一般会通过拦截JS原生的window.confirmwindow.prompt方法,从而达到H5向Native通信的目的。
    如,在 Webview 上添加 onJsConfirmonJsPrompt 监听(其实,监听window.console或者window.alert也是可以的,但是这两个方法在JS coding中比较常用,所以为了避免不必要的事件触发,一般我们不会选择在客户端劫持它们)。代码如下:

    webview.setWebChromeClient(new WebChromeClient());
    
    public class JSBridgeWebChromeClient extends WebChromeClient {
        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
            String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message, defaultValue);
            ......
            return true;
        }
    }
    

    2. Native调用Web函数

    反之,如果Native需要主动调用JS的方法,又该怎么做呢?

    很简单,只要 H5 将 JS 方法暴露在 Window 上给 Native 调用即可。
    是不是非常像客户端注册 Schema URI呢?

    JS注册好函数,Native就可以调用了。

    Android 4.4 以前,通过 loadUrl 方法,执行一段 JS 代码来实现(缺点是效率低,无法获得返回结果,且调用的时候会刷新 WebView):

    /**
     * js中声明全局函数
     */
    <script>
    function log(msg) {
        console.log(msg);
    }
    </script>
    
    --------------------------------------------------------------------
    /**
     * 设置与Js交互的权限
     */
    webSettings.setJavaScriptEnabled(true);
    
    private final class JSInterface{  
    
        @JavascriptInterface  
        public void showJsLog(String text){  
            webView.loadUrl("javascript:log('"+text+"')");  
        } 
    }  
    

    4.4 以后,可以使用 evaluateJavascript 方法实现(效率更高,可获取返回值,调用时候不刷新WebView)

    String text = "hello world";
    webView.evaluateJavascript("javascript:log('"+text+"')", new ValueCallback<String>() {
      @Override
      public void onReceiveValue(String value){
       ......
      }
    });
    

    小结

    Native和H5需要在接口设计上达成一致。只要API规定好,后续通信实现就不难了。

    相关文章

      网友评论

          本文标题:JSBridge小科普

          本文链接:https://www.haomeiwen.com/subject/nmhqhktx.html