什么是JSBridge ?
其实很好理解,是一个Java和JavaScript之间的一座桥梁。
为什么要用JSBridge?
它提供了安全、方便的方式从js调用Java代码和调用js代码从Java。
效果图:
可能看效果,刚开始会有点不明白。没事,仔细看下下面的介绍,相信你会对这个库有个深入的了解,其实内容不是很多!
首先引入github上的依赖库:
app目录下的.build文件
dependencies {
compile 'com.github.lzyzsd.jsbridge:library:1.0.0'
}
JS调用原生的方法,实现JS传参到原生,原生响应数据给JS。
JS中代码:
function testClick1() {
var str1 = document.getElementById("text1").value;
var str2 = document.getElementById("text2").value;
//call native method关键方法,调用原生方法
window.WebViewJavascriptBridge.callHandler(
'submitFromWeb'//原生的方法名
, {'param': str1}//带个原生方法的参数
, function(responseData) {//响应原生回调方法
document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData
}
);
}
原生中的方法:
//JS调用原生的方法,原生方法名与JS调用一致
webView.registerHandler("submitFromWeb", new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {//data是Js传来的数据,function方法是回调给Js的(带Str参数)
Log.i(TAG, "handler = submitFromWeb, data from web = " + data);//data即为JS传来的用户名
function.onCallBack("submitFromWeb exe, response data from Java");//返回给JS的数据
}
});
设置一个默认的handler,这样Js调用原生的方法时不需要声明Handler的名称
原生方法:
webView.setDefaultHandler(new DefaultHandler());
Js方法:
function testClick() {
var str1 = document.getElementById("text1").value;
var str2 = document.getElementById("text2").value;
//send message to native
var data = "name=" + str1 + ",pass=" + str2;
window.WebViewJavascriptBridge.send(
data
, function(responseData) {
document.getElementById("show").innerHTML = "repsonseData from java, data = " + responseData
}
);
这样Js调用原生的方法返回的响应数据,其实是DefaultHandler中实现的:
public class DefaultHandler implements BridgeHandler {
String TAG = "DefaultHandler";
public DefaultHandler() {
}
public void handler(String data, CallBackFunction function) {
if(function != null) {
function.onCallBack("DefaultHandler response data");
}
}
}
感觉这个方法不是特别实用,接着往下看!
原生调用Js中的放法:
原生方法:
@Override
public void onClick(View v) {
if (button.equals(v)) {
//原生通过callHandler方法,可以调起JS中名为functionInJs的方法
webView.callHandler("functionInJs", "data from Java", new CallBackFunction() {
@Override
public void onCallBack(String data) {
// TODO Auto-generated method stub
//data是Js的functionInJs中返回的数据
Log.i(TAG, "reponse data from js " + data);
}
});
}
}
JS中functionInJs的方法:
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
var data = {
'Javascript Responds': 'Wee!'
};
console.log('JS responding with', data);
responseCallback(data);
});
//这里就是Js注册的functionInJs方法,data即为原生带来的参数
bridge.registerHandler("functionInJs", function(data, responseCallback) {
//将原生带来的参数,显示在show标签位置
document.getElementById("show").innerHTML = ("data from Java: = " + data);
var responseData = "Javascript Says Right back aka!";
//调用responseCallback方法可以带传参数到原生
responseCallback(responseData);
});
})
OK,那么上面效果默认进来的时候show标签里面的数据是哪里来的呢,其实在原生的MainActivity中还有一个地方调用了Js中注册的functionInJs方法
MainActicvity方法中,这里user是原生定义的一个对象
//将User对象传递给JS的functionInJs方法,同样会走到上面Js的functionInJs方法中
webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() {
@Override
public void onCallBack(String data) {
}
});
再来看js里面选择文件上传的,调用原生的方法
js中只要声明:
<input type="file" value="打开文件" />
即可,主要工作在原生的MainActivity中执行:
webView.setWebChromeClient(new WebChromeClient() {
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType, String capture) {
this.openFileChooser(uploadMsg);
}
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType) {
this.openFileChooser(uploadMsg);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
pickFile();
}
});
pickFile()方法是原生调起本地相册
public void pickFile() {
Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);
chooserIntent.setType("image/*");
startActivityForResult(chooserIntent, RESULT_CODE);
}
Intent实现的回调函数
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == RESULT_CODE) {
if (null == mUploadMessage){
return;
}
Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
//这里调用该方法,将原生得到的数据返回给JS
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
ps:注意,这个lib将把WebViewJavascriptBridge 对象注入窗口对象,因此,在你的js中使用webviewJavascripBridge之前,你必须确认你的WebViewJavaScriptBridge存在,如果你的webViewJavasciptBridge不存在,你可以监听webViewJavascriptBridgeReady事件
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
},
false
);
}
}