最近转前端,在做一个混合项目,Android + 前端Vue技术,Vue没那么快上手,先分享一下Android部分的经验,后期会学习Flutter,和RN,边学边做边分享
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.布局页面
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
如果文章对你有帮助,欢迎点赞关注