最近研究HyBrid的两种方式:
//启动javascript
webView = (WebView) findViewById(R.id.webView);
//webView.setVerticalScrollbarOverlay(true);
String uri = "file:///android_asset/js_test2.html";
webView.loadUrl(uri);
// 添加客户端支持
webView.setWebChromeClient(new WebChromeClient());
// 设置WebView支持JavaScript
webView.getSettings().setJavaScriptEnabled(true);
注释比较清楚,不多解释。原生中代码:
// 调用js中的函数:jsFun(msg)
webView.loadUrl("javascript:jsFun('" + msg + "')");
直接通过Url加载javascript:+方法名
js中对应代码:
//在java中调用此方法
function jsFun(msg){
alert("我是js方法,被java调用,传递过来的参数是:"+msg);
}
如此即可调用在native中调用js代码:效果图如下:
native中添加:
// 添加js交互接口
webView.addJavascriptInterface(new MyJava(this), "javaObject");
addJavascriptInterface()源码:
* @param object the Java object to inject into this WebView's JavaScript
* context. Null values are ignored.
* @param name the name used to expose the object in JavaScript
*/
public void addJavascriptInterface(Object object, String name) {
checkThread();
mProvider.addJavascriptInterface(object, name);
}
第一个参数是Object对象:将Object对象注入到WebView的JavaScript的上下文中。
第二个参数name:在JavaScript暴露对象使用的名称。
通俗点讲:也就是用第二个参数名字在js中使用,来引用第一个java对象。
我们这个例子中自定义了一个MyJava对象:
private class MyJava {
private Context mContext;
public MyJava(Context context) {
this.mContext = context;
}
// 在js中调用window.javaObject.javaFun(name),便会触发此方法。
// api17版本以上加上注解
@JavascriptInterface
public void javaFun(String name) {
Toast.makeText(mContext, "我是java方法,被js调用,js传递过来的参数是:" + name,
Toast.LENGTH_LONG).show();
}
}
构造方法直接忽略。这句注释千万不能忽略。
@JavascriptInterface
涉及到4.2以上版本能否使用。4.2之前有个安全漏洞,4.2之后修复的方式,是js调用native的方法,方法上必须通过该注释注明才可以调用。
方法javaFun很简单,不多说,直接看js中如何调用。
js中添加:
function sendInfoToJava(){
//js调用java方法,并传递参数
var value = document.getElementById("name_input").value;
window.javaObject.javaFun(value);
}
通过window.javaObject.javaFun(value)调用native的方法。之前已经解释过javaObject引用MyJava对象。然后通过对象引用方法。PS : JsBridge类库地址。
查看类库结构:
导入步骤:
此处上面的example就不要导入了。一个样例,导入多余,还可能冲突。选择finish。导入第三方完毕。
高兴的太早了。主项目还调用不了这个导入的第三方包。
还需如下设置:
选择之前的命名的第三方类库,ok导入完毕。可以正常使用了。
PS:查阅了好多资料,之后总算是懂了。哎。好好学习,天天向上吧,少年。
通用部分:
xml:写一个BridgeWebView
说明:
样式很简单:上面一个按钮写着:button 演示Java调用web。下面一个第三方自定义webView控件。
第一版资源文件demo.html:(Js看不懂,可以看完下面的描述再看)
js调用java
Acitivity中:通过上面的Native按钮发消息给H5:
Activity初始化JsBridge:
setContentView(R.layout.activity_main);
webView = (BridgeWebView) findViewById(R.id.webView);
webView.loadUrl("file:///android_asset/demo.html");
只需要找到加载H5资源即可。Native点击事件如下:
@Override
public void onClick(View v) {
webView.callHandler("functionInJs", "传递消息给H5", new CallBackFunction() {
@Override
public void onCallBack(String data) {
}
});
}
H5如何能接收呢?如上注册了一个functionInJs,那么应该在H5中对应的写法。
说到这,必须先说说
H5初始化JsBridge:
H5初始化JsBridge第一步:
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
responseCallback(data);
});
})
H5初始化JsBridge第二步:
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
},
false
);
}
}
知道在哪初始化了,那么我就在[H5初始化JsBridge第一步]里面注册H5后如下:
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
responseCallback(data);
});
bridge.registerHandler("functionInJs", function(data, responseCallback) {
document.getElementById("show").innerHTML = ("Native发来的消息是:" + data);
var responseData = "Javascript Says Right back aka!";
responseCallback(responseData);
});
})
加上这一段代码就对应注册了functionInJs。
看看动图效果图:
第二版资源文件demo.html:
js调用java
说明:比第一版本多了一个点击事件。排除了第一版本的干扰Js代码。(H5初始化JsBridge不变)
既然是H5调用Native:先看Js的点击事件代码:
function go(){
window.WebViewJavascriptBridge.callHandler(
"Android",
"Hello~",
function(responseData){
document.getElementById('a').innerHTML = 'Native给我的数据: ' + responseData;
}
);
}
三个参数分别是:第一个参数:注册了一个Android。第二个参数:发送的消息内容是Hello~。第三个参数是一个回调。调用成功后,由Native返回responseData。
然后Native对应注册Android:
webView.registerHandler("Android", new BridgeHandler() {
@Override
public void handler(String s, CallBackFunction callBackFunction) {
Toast.makeText(MainActivity.this, "H5给我的数据:" + s, Toast.LENGTH_SHORT).show();
callBackFunction.onCallBack("fuck!");
}
});
这样子,对应注册完毕。
看个动图效果图:点击1被点击后,先弹出Native的Toast,然后回调了H5的内容文本。
正常来说,讲到这儿,应该是讲完了。但是这个第三方还自带懒人功能:Native调用H5:不注册参数。按照我们之前的例子来说就是不设置第一个参数functionInJs。反之,H5调用Native:不注册参数也可以调用默认的Native功能。
写一个类继承默认处理类DefaultHandler
class MDefaultHandler extends DefaultHandler{
@Override
public void handler(String data, CallBackFunction function) {
super.handler(data, function);
Log.d(TAG,data);
Toast.makeText(MainActivity.this,data,Toast.LENGTH_SHORT).show();
}
}
webView.setDefaultHandler(new MDefaultHandler());
Js调用的时候如何调用?
直接上demo.html:
js调用java
可见只是这儿有所修改:
window.WebViewJavascriptBridge.send(
"被传递的Data"
, function(responseData) {
document.getElementById("a").innerHTML = "H5默认调用Native" + responseData
}
);
改变:只有两个参数了。方法名变成了send。看看Js初始化第一步:
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
responseCallback(data);
});
})
Native发送默认消息方式非常简单:点击事件里面调用一下即可:
@Override
public void onClick(View v) {
webView.send("hello来自Native的默认消息");
}
为了方便验证:将Js初始化第一步改成如下:
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
document.getElementById("a").innerHTML = "来自Native的:" + message;
responseCallback(data);
});
})
也就是在id等于a的文本处展示。
动图效果图如下:
Over~打算再写一章关于JsBridge的原理,看看我能不能读懂大神的源码吧。