最近研究HyBrid的两种方式:
一、直接原生WebView
1)初始化WebView:
<span style="white-space:pre"> </span>//启动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);注释比较清楚,不多解释。
2)WebView与js通信
原生中代码:
// 调用js中的函数:jsFun(msg) webView.loadUrl("javascript:jsFun('" + msg + "')");直接通过Url加载javascript:+方法名
js中对应代码:
//在java中调用此方法 function jsFun(msg){ alert("我是js方法,被java调用,传递过来的参数是:"+msg); }
如此即可调用在native中调用js代码:效果图如下:
3)js与WebView通信
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对象。然后通过对象引用方法。
js引用native动画效果如下:
二、JsBridge方法实现HyBrid
一、导入第三方类库:
PS : JsBridge类库地址。
二、Android Studio导入第三方类库说简单简单,说难也难。
查看类库结构:
导入步骤:
1)先复制上述第三方类库到app平级处:如下
2)导入第三方类库:如下图:按顺序:
此处上面的example就不要导入了。一个样例,导入多余,还可能冲突。选择finish。导入第三方完毕。
高兴的太早了。主项目还调用不了这个导入的第三方包。
还需如下设置:
选择之前的命名的第三方类库,ok导入完毕。可以正常使用了。
三、使用JsBridge实现
PS:查阅了好多资料,之后总算是懂了。哎。好好学习,天天向上吧,少年。
通用部分:
1)使用JsBridge的WebView:BridgeWebView
xml:写一个BridgeWebView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- button 演示Java调用web --> <Button android:id="@+id/button" android:layout_width="match_parent" android:text="button 演示Java调用web" android:layout_height="48dp" /> <!-- webview 演示web调用Java --> <com.github.lzyzsd.jsbridge.BridgeWebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" > </com.github.lzyzsd.jsbridge.BridgeWebView> </LinearLayout>说明:
样式很简单:上面一个按钮写着:button 演示Java调用web。下面一个第三方自定义webView控件。
第一版资源文件demo.html:(Js看不懂,可以看完下面的描述再看)
<html> <head> <meta content="text/html; charset=utf-8" http-equiv="content-type"> <title> js调用java </title> </head> <body> <a id="show"></a> <script> function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); } } 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); }); }) </script> </body> </html>
2)直入主题:Native发送消息给H5
Acitivity中:通过上面的Native按钮发消息给H5:
Activity初始化JsBridge:
<span style="white-space:pre"> </span>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。
看看动图效果图:
3)直入主题:H5发送消息给Native
第二版资源文件demo.html:
<html> <head> <meta content="text/html; charset=utf-8" http-equiv="content-type"> <title> js调用java </title> </head> <body> <input type="button" value="点击1" onclick="go()"/> <a id="a"></a> <script> function go(){ window.WebViewJavascriptBridge.callHandler( "Android", "Hello~", function(responseData){ document.getElementById('a').innerHTML = 'Native给我的数据: ' + responseData; } ); } function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); } } connectWebViewJavascriptBridge(function(bridge) { bridge.init(function(message, responseCallback) { console.log('JS got a message', message); responseCallback(data); }); }) </script> </body> </html>说明:比第一版本多了一个点击事件。排除了第一版本的干扰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功能。
4)Native默认设置:H5发送消息给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设置:
webView.setDefaultHandler(new MDefaultHandler());Js调用的时候如何调用?
直接上demo.html:
<html> <head> <meta content="text/html; charset=utf-8" http-equiv="content-type"> <title> js调用java </title> </head> <body> <input type="button" value="点击1" onclick="go()"/> <a id="a"></a> <script> function go(){ window.WebViewJavascriptBridge.send( "被传递的Data" , function(responseData) { document.getElementById("a").innerHTML = "H5默认调用Native" + responseData } ); } function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); } } connectWebViewJavascriptBridge(function(bridge) { bridge.init(function(message, responseCallback) { console.log('JS got a message', message); responseCallback(data); }); }) </script> </body> </html>可见只是这儿有所修改:
window.WebViewJavascriptBridge.send( "被传递的Data" , function(responseData) { document.getElementById("a").innerHTML = "H5默认调用Native" + responseData } );改变:只有两个参数了。方法名变成了send。
看看动画效果图:
5)Js默认设置:Native发送消息给H5。
看看Js初始化第一步:
connectWebViewJavascriptBridge(function(bridge) { bridge.init(function(message, responseCallback) { console.log('JS got a message', message); responseCallback(data); }); })
此处的message其实就是默认的发来的消息。
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的原理,看看我能不能读懂大神的源码吧。