本文的目的是學習如何進行Android native+html5的混合開發。javascript
首先什麼是Android native+html5的混合開發?css
一般來講就是使用html5+css+JavaScript等Web前端開發技術開發出html文件,再經過Android 的WebView加載html文件實現App的UI開發 ,Android系統提供數據庫、通信錄、攝像頭、音頻等API供JavaScript調用。html
所以在混合開發過程當中須要解決下面三個問題:前端
1.Android 如何調用JavaScript方法html5
2.JavaScript如何調用Android方法java
3.JavaScrpit如何調用Android異步方法android
4.Android如何調用JavaScript的異步方法web
這四個問題解決以後,Android native+html5的混合開發就只須要分別進行html5+css+JavaScript 的Web前端開發和Android native開發了。數據庫
下面經過示例來學習如何解決上面四個問題。框架
1.1 設置WebView的WebSettings使WebView 能夠執行JavaScript。
webview = (WebView) findViewById(R.id.myWebView); // 獲得設置屬性的對象
WebSettings webSettings = webview.getSettings(); // 使能JavaScript
webSettings.setJavaScriptEnabled(true); // 支持中文,不然頁面中中文顯示亂碼
webSettings.setDefaultTextEncodingName("UTF-8");
1.2 爲WebView添加JavascriptInterface,這一步相當重要,爲JavaScript調用Android代碼提供了接口
//傳入一個Java對象和一個接口名,在JavaScript代碼中用這個接口名代替這個對象,經過接口名調用Android接口的方法
webview.addJavascriptInterface(new JavascriptInterfaceImpl(this, webview), "Android");
JavascriptInterfaceImpl 的實現見Demo。
在 JavascriptInterfaceImpl 中定義了
1 1.void showToast(String toast)//顯示Toast
3 2.String syncExec()//同步執行方法
5 3.void asyncExec(final String msg, final String callbackId)//異步執行方法
6 4.
四個方法,下面會經過這四個方法,來學習JavaScript和Android之間的相互調用。
1.3 爲WebView設置WebViewClient,這一步對使用JavaScript不是必須的。
// WebViewClient 主要幫助WebView處理各類通知、請求事件的
webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } });
1.4 爲WebView設置WebChromeClient,不設置WebChromeClient的話,JavaScript的彈框消息會沒法顯示。
1 // WebChromeClient主要用來輔助WebView處理Javascript的對話框、網站圖標、網站標題以及網頁加載進度等
2 webview.setWebChromeClient(new WebChromeClient() { 3 @Override 4 public void onReceivedTitle(WebView view, String title) { 5 } 6
7 @Override 8 public boolean onJsAlert(WebView view, String url, String message, 9 JsResult result) { 10 return super.onJsAlert(view, url, message, result); 11 } 12 });
1.5 加載本地html頁面
// 載入頁面:本地html資源文件
webview.loadUrl("file:///android_asset/sample.html");
Sample.html文件放置在assets目錄下面,Sample.html的具體實現查看Demo
Android調用JavaScript方法很是簡單,例如 Sample.html中定義了一個名爲myFunction的方法
1 function myFunction() 2 { 3 alert("Hello World!"); 4 } 5
在Android裏面執行下面代碼便可調用該JavaScript方法
1 webview.loadUrl("javascript:myFunction()");
注意兩點:
1.webview.loadUrl()方法須要在UI線程中調用
2.調用的JavaScript方法須要定義在WebView加載的html文件中
在Android4.4以上的系統還提供了另一個方法能夠執行JavaScrpit代碼
public void evaluateJavascript (String script, ValueCallback<String> resultCallback)
在1.2中咱們給WebView添加JavascriptInterface,JavascriptInterface的實現類是JavascriptInterfaceImpl,接口名是"Android",所以咱們能夠在JavaScript代碼中經過Android這個接口名來調用JavascriptInterfaceImpl裏面的Android方法。
例如,調用JavascriptInterfaceImpl的syncExec方法.該方法的結果是同步返回的
1 //調用綁定的Java對象的方法,同步顯示android返回的內容
2 function showAndroidSyncMsg() 3 { 4 console.log("showAndroiHello method"); 5 var str = Android.syncExec(); 6 alert(str); 7 }
JavaScript如何調用Android異步方法是一個難點,由於沒有提供直接的接口能夠調用Android異步方法,而且接收Android異步返回的結果.在此以前咱們先看下Java是如何處理異步方法的
1 public interface Callback { 2 void onResult(String result); 3 } 4 5 public void asyncFun(final Callback callback) { 6 new Thread() { 7 @Override 8 public void run() { 9 SystemClock.sleep(3 * 1000); 10 callback.onResult("async result"); 11 } 12 }.start(); 13 } 14 15 public void test() { 16 this.asyncFun(new Callback() { 17 18 @Override 19 public void onResult(String result) { 20 Log.d(TAG, "result == " + result); 21 } 22 }); 23 }
在Java中是經過定義一個回調接口,在異步方法執行完後,在回調這個回調接口的方法,將結果傳給調用者.
一樣的道理,咱們也能夠爲JavaScript調用Android異步方法設計相同的調用模式.
例如
1 /**
2 * 異步方法 3 * @param msg 4 * @param callbackId 5 */
6 @JavascriptInterface 7 public void asyncExec(final String msg, final String callbackId) { 8 new Thread() { 9 @Override 10 public void run() { 11 SystemClock.sleep(5 * 1000); 12 mHandler.post(new Runnable() { 13 @Override 14 public void run() { 15 String url = "javascript:" + callbackId + "('" + msg 16 + " from android " + "')"; 17 mWebView.loadUrl(url); 18 } 19 }); 20 } 21 }.start(); 22 }
該方法有兩個參數,一個是傳進來的數據,一個是要回調的JavaScript方法名.asyncExec在異步執行完後,經過webview.loadUrl()方法將結果回調給JavaScript的回調方法.
在JavaScript端須要定義一個回調方法接收回調結果,例如:
//調用綁定的Java對象的方法,異步顯示android返回的內容
function showAndroidAsyncMsg() { console.log("showAndroidAsyncMsg method"); //異步回調方法
//調用android 異步接口
Android.asyncExec("異步消息", "onCallback"); } // 定義回調方法
function onCallback(msg) { alert(msg); }
Android調用JavaScript異步方法和第二節中調用JavaScript方法是同樣的,只是這裏的JavaScript方法是異步的,關於JavaScript的異步實現,能夠參照
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html
JavaScript的異步方法也能夠經過回調的方式,將結果回調給Android.首先須要在JavascriptInterfaceImpl中定義一個方法,接收JavaScript的回調結果,例如本文中的
public void callBack(String msg) //接收JavaScript的異步消息
編寫一個JavaScript異步方法示例
1 //異步方法 2 function asyncFun() { 3 console.log("asyncFun method"); 4 setTimeout(function() { 5 console.log("異步執行"); 6 Android.callBack("來自JavaScript的異步消息"); 7 }, 8 5000); 9 }
在Android中調用該異步方法
1 // 調用JavaScript異步方法 2 webview.loadUrl("javascript:asyncFun()");
至此,已經學習了Android和JavaScript之間的相互調用,Android版本的Html5開發框架PhoneGap在實現Android和JavaScript的相互調用的時候和本文使用的相同的方式,包括異步調用的設計.可是PhoneGap的核心Cordova對參數類型的轉換,異步消息的隊列管理作了很好的封裝,讓使用者能夠更簡單的實現Android和JavaScript之間的混合開發.下一篇文章會介紹Cordova框架.
思考:
1.Android和JavaScript之間能傳哪些類型的參數?若是將各類類型的Android參數傳遞給JavaScript,JavaScript如何解析?
Demo下載地址
http://files.cnblogs.com/files/kuangbiao/Html5Demo.tar.gz
html相關知識參考
http://www.w3cschool.cn/index-5.html
推薦javascript教程
<javascript權威指南>