android jsbridge实现原理简述

版权声明:本文为博主原创文章,转载希望能注明出处,感谢。 https://blog.csdn.net/u010126792/article/details/82836741

假如生活欺骗了你,假如工作到处不顺,请放松心态,提升自己,终有一天你会适应,然后。。。。。。。。。。。。。。。

本篇是面试小问题专栏的开篇文章,由于是面试小问题的解答,所以所有的文章都会力求把问题说明白的同时精简字数,可能有理解不到位的地方后续会慢慢完善。

h5可以作为移动端跨平台的一种方式,其他方式还有rnjs,flutter,weekx等,android或者ios为了实现和js的交互都提供了原生方法,但都存在一定的问题,这时jsbridge就诞生了。

android原生和js交互方式,调用js,loadurl通用,evaluateJavascript支持回调但都涉及版本问题,js调用原生不同版本又设置到安全问题,虽然新版利用@JavascriptInterface  解决了安全问题但现实中依然有很多低版本。

jsbridge 优点说明:

1 统一android ,ios两边的调用方式,使绑定和调用函数接口统一,

2 完美解决安全性问题和回调函数问题。

原理说明:

交互通道:

要实现原生和js交互首先需要一条双方交互的通道,一般的jsbridge都是利用拦截prompt函数,webView端拦截了js端发送的prompt函数,可以获取上面的文本。原生执行js还是利用原来的loadurl。

重写webView和 WebChromeClient,拦截prompt。

扫描二维码关注公众号,回复: 3368378 查看本文章
 public static class WebChromeClientEx extends WebChromeClient {

        public void onProgressChanged(WebView view, int newProgress) {
            super.onProgressChanged(view, newProgress);
        }

        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
            Logger.d("JsBridge","onJsPrompt: " + message);

            try {
                //根据协议进行解析
                JSONObject jsonObject = new JSONObject(message);
                if (JavascriptBridge.matchBridgeProtocol(jsonObject)) {
                    result.confirm("prompt ok");
                    JavascriptBridge.onGetDataFromJs(view, jsonObject);
                } else {
                    result.confirm("data does not match bridge protocol");
                }
            } catch (Exception e) {
                e.printStackTrace();
                result.confirm("exception");
            }

            return true;
        }

        public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
            if (view instanceof BaseWebView) {
                SimpleToastHelper.showShortToast(view.getContext(), message);
            }
            result.confirm();
            return true;
        }

        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            if (view instanceof BaseWebView) {
                SimpleToastHelper.showShortToast(view.getContext(), message);
            }
            result.confirm();
            return true;
        }
    }

定义协议:

js调用原生,会通过调用prompt函数,webView获取到prompt传递的文本(协议),根据自定义协议解析文本,执行特定原生函数。

js端如何调用原生的函数和回调如何处理:

native(原生)的函数A会被js调用,首先A和实现会被存储到本地的map中,然后native端回调用js端写好的注册函数,在对应的js端生成一个代表原生函数A的js函数B(其实两者之间没有必然联系,不想系统提供的js调用native的方式,没有注册对象,这样就保证了安全性),然后js调用想调用原生A函数时,就调用js函数B,利用prompt把调用原生A的协议传过去,onjsprompt拦截协议,调用本地A函数。

所以jsbridge都会提供H5端注册代码用于生成js的javascriptBridge对象,类似

(function () {
            if (window.bridge) {
                return;
            }

            window.bridge = {};
            var messages = {};
            var call_id = 0;

native函数需要调用register函数,在h5端生成对应的函数           

bridge.register = function (name) {
                if (this[name]) {
                    return;
                }
                
                this[name] = function (params, callback) {
                
                    invokeNative(name, params, callback);
                };
            };

            bridge.obtain = function (id) {
                return JSON.stringify(messages[id].params);
            };

            bridge.callback = function (id, data) {
                var message = messages[id];
                if (!message) {
                    return;
                }

                if (message.callback) {
                    message.callback(JSON.parse(data));
                }
                delete messages[id];
            };
        

       最终实现调用原生的方法  prompt

           function invokeNative (name, params, callback) {
                call_id ++;
                messages[call_id] = {'params' : params, 'callback' : callback};

                if (navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Adr') > -1) {
                    prompt(JSON.stringify({'cmd':name, 'id':call_id, 'params':params}), '');
                } else {
                    var iframe = document.createElement('iframe');
                    iframe.src = 'bridge://invoke.native.method?handler=' + name + '&id=' + call_id;
                    iframe.style.display = 'none';
                    document.documentElement.appendChild(iframe);
                    setTimeout(function () { document.documentElement.removeChild(iframe); }, 0);
                }
            }
        })();

原生调用js如何实现回调:

可以Native根据协议生成js对象,webView加载网页时将本地js注入到网页中,原生调用注入js中的函数,js端接收调用首先调用js函数,然后根据协议调用原生端的对调函数。

jsbridge简单介绍就到这里。

猜你喜欢

转载自blog.csdn.net/u010126792/article/details/82836741
今日推荐