上一篇簡單介紹了Androi與前端H5 js的交互方式,那些方式對於一些簡單的交互足夠了,但是如果涉及到複雜的交互就很乏力,下面就來介紹一個Github上用來處理Android與js較複雜的交互的框架。
框架地址:
https://github.com/jesse01/WebViewJavascriptBridge
步驟:
- 下載代碼,找到WebViewJavascriptBridge文件夾,注意這個文件夾下有清單文件,層級不要弄錯。
- 在已有的工程中將這個項目以module的形式導入到AS中(框架使用ES編寫的),如圖
項目結構:
首先看assets文件夾下的html文件和txt文件,txt文件全是js代碼,主要用來搭建與java交互的橋樑,不需要管,後面會提到。html文件中包含於java交互的代碼。
WVJBWebViewClient也是用來搭建橋樑的不需要細看。只需要看一下onPageFinished方法,這裏會加載上面的txt文件,在java中執行txt中的js代碼,構建橋樑
@Override public void onPageFinished(WebView view, String url) { try { InputStream is = webView.getContext().getAssets() .open("WebViewJavascriptBridge.js.txt"); int size = is.available(); byte[] buffer = new byte[size]; is.read(buffer); is.close(); String js = new String(buffer); executeJavascript(js); } catch (IOException e) { e.printStackTrace(); } if (startupMessageQueue != null) { for (int i = 0; i < startupMessageQueue.size(); i++) { dispatchMessage(startupMessageQueue.get(i)); } startupMessageQueue = null; } super.onPageFinished(view, url); } public void executeJavascript(String script) { executeJavascript(script, null); } public void executeJavascript(String script, final JavascriptCallback callback) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { webView.evaluateJavascript(script, new ValueCallback<String>() { @Override public void onReceiveValue(String value) { if (callback != null) { if (value != null && value.startsWith("\"") && value.endsWith("\"")) { value = value.substring(1, value.length() - 1) .replaceAll("\\\\", ""); } callback.onReceiveValue(value); } } }); } else { if (callback != null) { myInterface.addCallback(++uniqueId + "", callback); webView.loadUrl("javascript:window." + kInterface + ".onResultForScript(" + uniqueId + "," + script + ")"); } else { webView.loadUrl("javascript:" + script); } } }
上面會根據不通過的Android系統版本使用不同的方法來執行這些js代碼。
交互
這裏爲了看起來清楚,把英文提示改成了漢字
JAVA→JS
第一種方式:
JAVA代碼findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { webViewClient.send("來自java的數據", new WVJBWebViewClient.WVJBResponseCallback() { @Override public void callback(Object data) { Toast.makeText(MainActivity.this, "js接收到數據並返回數據: " + data, Toast.LENGTH_LONG).show(); } }); } });
JS代碼
bridge.init(function(message, responseCallback) { log('JS收到數據', message) var data = { 'js接收到消息了':'啦啦!' } log('JS返回數據', data) responseCallback(data) })
這種方式java傳過來的參數都會統一調用bridge.init()中設置的回調方法的方法。可以在這裏對message進行判斷類型,執行不同的操作。
第二種方式:
JAVA代碼
findViewById(R.id.button2).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { webViewClient.callHandler("javaCallJs", new JSONObject("{\"java的問候\": \"你好, JS!\" }"), new WVJBWebViewClient.WVJBResponseCallback() { @Override public void callback(Object data) { Toast.makeText(MainActivity.this, "來自js的迴應:" + data, Toast.LENGTH_LONG).show(); } }); } catch (JSONException e) { e.printStackTrace(); } } });
JS代碼
bridge.registerHandler('javaCallJs', function(data, responseCallback) { log('java調用action javaCallJs', data) var responseData = { 'js收到':'哇嗚' } log('JS的響應', responseData) responseCallback(responseData) })
效果圖
這種方式是專門的在js中註冊一個action,在java中callHandler方法,傳入action,調用專門的js方法。對於比較複雜交互來說代碼還是比較清楚明瞭的。
JS→JAVA
第一種方式:
JAVA代碼
super(webView, new WVJBWebViewClient.WVJBHandler() { @Override public void request(Object data, WVJBResponseCallback callback) { Toast.makeText(MainActivity.this, "接到js的數據: " + data, Toast.LENGTH_LONG).show(); callback.callback("收到了你的問候,Js"); } });
JS代碼
var button = document.getElementById('buttons').appendChild(document.createElement('button')) button.innerHTML = '調用java並傳數據' button.onclick = function(e) { e.preventDefault() var data = '你好啊, Java' log('JS發送消息給java', data) bridge.send(data, function(responseData) { log('來自java的迴應', responseData) }) }
效果圖
和java調用js第一種方式一樣,這個會統一調用,通過message的類型進行判斷進行不同的操作
第二種方式:
JAVA代碼
registerHandler("jsCallJava", new WVJBWebViewClient.WVJBHandler() { @Override public void request(Object data, WVJBResponseCallback callback) { Toast.makeText(MainActivity.this, "收到Js的數據 " + data, Toast.LENGTH_LONG).show(); callback.callback("收到你問候,謝謝!)"); } });
JS代碼
var callbackButton = document.getElementById('buttons').appendChild(document.createElement('button')) callbackButton.innerHTML = '調用java註冊的action並傳數據' callbackButton.onclick = function(e) { e.preventDefault() log('JS調用java action "jsCallJava"') bridge.callHandler('jsCallJava', {'Js的問候': '你好,java!'}, function(response) { log('JS收到java的響應', response) }) }
效果圖
這種方式是在java中註冊了action,在js中調用action。對於複雜的情況比較合適。
對於這個框架就簡單的介紹到這,下一篇將會對這一框架進行封裝,達到在html中直接引用一個js文件就實現專門的action。