一丶概述

最近转前端,在做一个混合项目,Android + 前端Vue技术,Vue没那么快上手,先分享一下Android部分的经验,后期会学习Flutter,和RN,边学边做边分享

二丶效果演示

三丶JSBridge引入

1.什么是JSBridge

JSBridge是移动UIView和Html交互通信的桥梁,就是实现java(ios为oc)和js的互相调用的桥梁。出于安全考虑,android自4.4后不建议使用@JavascriptInterface注解,所以Android4.4以后就没有了默认的Jsbridge的实现,替代了WebView的自带JavascriptInterface的接口,使得我们的开发更加灵活和安全。

说明:

(1).JSBridge作用是移动端和前端通信;

(2).Java  oc  js要分别实现;

(3).替代JavascriptInterface的接口,安全;

2.JSBridge集成

GitHub全局搜索JSBridge

star最多,Android端一般会选择上面一个,iOS端会选择下面一个

这样前端的同事就得注意了,两者初始化方法不一样,需要分别对接解决兼容问题

当然也有大牛解决这个问题

DSBridge

这里由于跟iOS没达成一致选择了上面的方式

四丶效果实现

效果作用,演示Android与前端方法互相调用

1.添加依赖

repositories {    // ...    maven { url "https://jitpack.io" }}dependencies {    compile 'com.github.lzyzsd:jsbridge:1.0.4'}

2.布局页面

<?xml version="1.0" encoding="utf-8"?>        

3.Android端桥注册及调用

public class MixedActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.mixed_activity);        Button btn = (Button) findViewById(R.id.btn);        final EditText etText = (EditText) findViewById(R.id.et_text);        final BridgeWebView bridgeWebView = (BridgeWebView) findViewById(R.id.JsBridgeWebView);        bridgeWebView.setDefaultHandler(new DefaultHandler());        bridgeWebView.setWebChromeClient(new WebChromeClient());        bridgeWebView.loadUrl("file:///android_asset/a.html");        /**         * js调用Android         *         *  参数一:getUserInfo就是注册供JS调用的方法名,         *  参数二:data是JS传过来的参数,         *  参数三:CallBackFunction 函数中需要把JS需要的response返回给JS         */        bridgeWebView.registerHandler("submitFromWeb", new BridgeHandler() {            @Override            public void handler(String data, CallBackFunction function) {                Log.e("TAG", "js返回:" + data);                //显示js传递给Android的消息                Toast.makeText(MixedActivity.this, "js返回:" + data, Toast.LENGTH_LONG).show();                //Android返回给JS的消息                function.onCallBack("我是js调用Android返回数据:" + etText.getText().toString());            }        });        /**         * Android调用js         *         * 参数一:js中的方法名称         * 参数二:Android传递给js数据         * 参数三:回调接口,data为Android调用js方法的返回数据         */        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                bridgeWebView.callHandler("functionInJs", "Android调用js的方法", new CallBackFunction() {                    @Override                    public void onCallBack(String data) {                        Log.e("TAG", "onCallBack:" + data);                        Toast.makeText(MixedActivity.this, data, Toast.LENGTH_LONG).show();                    }                });            }        });    }}

注意点:1.桥名称相同;2.传递数据类型相同(android只能String,所以统一String)

4.前端JSBridge实现

这里要做重点注意,这边开发由于是iOS与前端先调试完,再调试Android,方法各种调不通,明明参考的同一篇博客,就是无效。原因呢:注册的方式不对,与iOS的方式只有细节上的不同。

丢给前端一个文件,分别做兼容,才解决问题

WebViewJavascriptBridge.js

//notation: js file can only use this kind of comments//since comments will cause error when use in webview.loadurl,//comments will be remove by java use regexp(function() {    if (window.WebViewJavascriptBridge) {        return;    }    var messagingIframe;    var sendMessageQueue = [];    var receiveMessageQueue = [];    var messageHandlers = {};    var CUSTOM_PROTOCOL_SCHEME = 'yy';    var QUEUE_HAS_MESSAGE = '__QUEUE_MESSAGE__/';    var responseCallbacks = {};    var uniqueId = 1;    function _createQueueReadyIframe(doc) {        messagingIframe = doc.createElement('iframe');        messagingIframe.style.display = 'none';        doc.documentElement.appendChild(messagingIframe);    }    //set default messageHandler    function init(messageHandler) {        if (WebViewJavascriptBridge._messageHandler) {            throw new Error('WebViewJavascriptBridge.init called twice');        }        WebViewJavascriptBridge._messageHandler = messageHandler;        var receivedMessages = receiveMessageQueue;        receiveMessageQueue = null;        for (var i = 0; i < receivedMessages.length; i++) {            _dispatchMessageFromNative(receivedMessages[i]);        }    }    function send(data, responseCallback) {        _doSend({            data: data        }, responseCallback);    }    function registerHandler(handlerName, handler) {        messageHandlers[handlerName] = handler;    }    function callHandler(handlerName, data, responseCallback) {        _doSend({            handlerName: handlerName,            data: data        }, responseCallback);    }    //sendMessage add message, 触发native处理 sendMessage    function _doSend(message, responseCallback) {        if (responseCallback) {            var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime();            responseCallbacks[callbackId] = responseCallback;            message.callbackId = callbackId;        }        sendMessageQueue.push(message);        messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE;    }    // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容    function _fetchQueue() {        var messageQueueString = JSON.stringify(sendMessageQueue);        sendMessageQueue = [];        //android can't read directly the return data, so we can reload iframe src to communicate with java        messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);    }    //提供给native使用,    function _dispatchMessageFromNative(messageJSON) {        setTimeout(function() {            var message = JSON.parse(messageJSON);            var responseCallback;            //java call finished, now need to call js callback function            if (message.responseId) {                responseCallback = responseCallbacks[message.responseId];                if (!responseCallback) {                    return;                }                responseCallback(message.responseData);                delete responseCallbacks[message.responseId];            } else {                //直接发送                if (message.callbackId) {                    var callbackResponseId = message.callbackId;                    responseCallback = function(responseData) {                        _doSend({                            responseId: callbackResponseId,                            responseData: responseData                        });                    };                }                var handler = WebViewJavascriptBridge._messageHandler;                if (message.handlerName) {                    handler = messageHandlers[message.handlerName];                }                //查找指定handler                try {                    handler(message.data, responseCallback);                } catch (exception) {                    if (typeof console != 'undefined') {                        console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception);                    }                }            }        });    }    //提供给native调用,receiveMessageQueue 在会在页面加载完后赋值为null,所以    function _handleMessageFromNative(messageJSON) {        console.log(messageJSON);        if (receiveMessageQueue && receiveMessageQueue.length > 0) {            receiveMessageQueue.push(messageJSON);        } else {            _dispatchMessageFromNative(messageJSON);        }    }    var WebViewJavascriptBridge = window.WebViewJavascriptBridge = {        init: init,        send: send,        registerHandler: registerHandler,        callHandler: callHandler,        _fetchQueue: _fetchQueue,        _handleMessageFromNative: _handleMessageFromNative    };    var doc = document;    _createQueueReadyIframe(doc);    var readyEvent = doc.createEvent('Events');    readyEvent.initEvent('WebViewJavascriptBridgeReady');    readyEvent.bridge = WebViewJavascriptBridge;    doc.dispatchEvent(readyEvent);})();

jsbridgewebview加载的html

        js调用java

写在最后微信扫码提问

源码下载:

https://github.com/JinBoy23520/CoderToDeveloperByTCLer

如果文章对你有帮助,欢迎点赞关注

 

更多相关文章

  1. Android工程引用另外一个工程的正确/错误方法
  2. Android(安卓)和 Webview 如何相互 sayHello(一)
  3. 简述Android(安卓)解决65536/64K方法数限制方案
  4. 调用Android常用应用的接口
  5. Android(安卓)—— 自定义View的实现方法
  6. Android真机连接Eclipse时,打不开File Explorer下的data文件夹解
  7. Android(安卓)UI事件处理、focus处理
  8. Qt on Android: http下载与Json解析
  9. Android中的单例模式

随机推荐

  1. Node 模块
  2. 怎么画好人体动态?漫画人体结构绘画入门
  3. 事件,条件,列表渲染,计算属性与侦听器,组件之
  4. vue常用术语与常用指令
  5. R语言数据挖掘实践——关联分析预测用户
  6. Spring Cloud OpenFeign 超时与重试
  7. JS的闭包、访问器属性、类与对象的创建和
  8. php字符串中转义成特殊字符实例讲解
  9. 如何用js实现鼠标向上滚动时浮动导航
  10. vue常用术语与指令