失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android混合开发(一)——移动端与前端交互之JSBridge引入

Android混合开发(一)——移动端与前端交互之JSBridge引入

时间:2018-09-11 02:49:39

相关推荐

Android混合开发(一)——移动端与前端交互之JSBridge引入

一丶概述

最近转前端,在做一个混合项目,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"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:id="@+id/et_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="请输入测试数据"/><Buttonandroid:id="@+id/btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="调用js方法"/><com.github.lzyzsd.jsbridge.BridgeWebViewandroid:id="@+id/JsBridgeWebView"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>

3.Android端桥注册及调用

public class MixedActivity extends AppCompatActivity {@Overrideprotected 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() {@Overridepublic 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() {@Overridepublic void onClick(View view) {bridgeWebView.callHandler("functionInJs", "Android调用js的方法", new CallBackFunction() {@Overridepublic 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 messageHandlerfunction 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处理 sendMessagefunction _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 javamessagingIframe.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 functionif (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];}//查找指定handlertry {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

<html><head><meta content="text/html; charset=utf-8" http-equiv="content-type"><title>js调用java</title></head><body><p><input type="text" id="text1" value="请输入测试数据" width="400px" height="200px"/></p><p><input type="button" id="enter" value="调用安卓的方法" onclick="testClick();"/></p><script>//js调用Android方法:接收Android传递过来的数据,并做处理function testClick() {//参数一:调用java中的方法 submitFromWeb是方法名,必须和Android中注册时候的方法名称保持一致//参数二:返回给Android端的数据,可以为字符串,json等信息//参数三:js接收到Android传递过来的数据之后的相应处理逻辑window.WebViewJavascriptBridge.callHandler('submitFromWeb', {'param': "JS成功接收到数据---"}, function(responseData) {alert(responseData)});}//JS注册事件监听function connectWebViewJavascriptBridge(callback) {if (window.WebViewJavascriptBridge) {callback(WebViewJavascriptBridge)} else {document.addEventListener('WebViewJavascriptBridgeReady', function() {callback(WebViewJavascriptBridge)},false);}}//注册回调函数,第一次连接时调用 初始化函数connectWebViewJavascriptBridge(function(bridge) {//初始化bridge.init(function(message, responseCallback) {var data = {'Javascript Responds': 'Wee!'};responseCallback(data);});//Android调用js方法:functionInJs方法名称需要保持一致 ,并返回给Android通知bridge.registerHandler("functionInJs", function(data, responseCallback) {alert(data);var data = document.getElementById("text1").value;var responseData = "我是Android调用js方法返回的数据---"+ data;responseCallback(responseData);});})</script></body></html>

写在最后微信扫码提问

源码下载:

/JinBoy23520/CoderToDeveloperByTCLer

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

如果觉得《Android混合开发(一)——移动端与前端交互之JSBridge引入》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。