關於WebView
我們知道目前android市場上的一些應用採用的開發方式大致分爲三種:Native
App、Web App、Hybrid
App。本文主要是Hybrid App中實現的主要技術native組件與js的數據交互的理解以及實現。
Android API中提供了WebView組件來實現對html的渲染。所謂的HybridApp開發方式即是彙集了HTML5、CSS3、jS的相關開發技術,以及數據交換格式json/XML。這顯然是Web開發工程師的技能。正是因爲如此,衆多中小企業選擇了這種開發方式來減少對android開發工程師的過度依賴,至於這三種開發方式的比較與優劣不在本文考慮之列。
有了WebView這個組件,Android應用開發技術也就轉嫁到html與java數據交互上來。說白了就是js與WebView的數據交互,這就是本文所要討論的。
WebView與js的數據交互
1. WebView中載入靜態頁面
將WebView添加到應用中。和原生控件一樣,在layout引入WebView控件。代碼片段如下:
-
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-
android:id="@+id/linearLayout"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:background="#000"
-
android:orientation="horizontal" >
-
<WebView
-
android:id="@+id/webview"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
/>
-
</LinearLayout>
載入頁面:
-
webView = (WebView) findViewById(R.id.webview);
-
webView.loadUrl("file:///file:///android_asset/page.html");
page.html存儲在工程文件的assets根目錄下。
2. 引入jquery
mobile
引入js框架讓我們編寫的html頁面更接近於原生控件的顯示效果。目前主流的移動應用js框架有:jquery
mobile和sencha touch(jquery
mobile與sencha touch的選型不在本文討論範圍)。本文選擇使用jquery
mobile。
首先,在webview添加對js的支持:
-
WebSettings setting = webView.getSettings();
-
setting.setJavaScriptEnabled(true);
增加對中文的支持:
-
WebSettings setting = webView.getSettings();
-
setting.setDefaultTextEncodingName("GBK");
設置頁面滾動條風格:
-
webView.setScrollBarStyle(0);
jquery mobile提供的標準頁面模板TemplateForJQuery.html:
-
<!DOCTYPE html>
-
<html>
-
<head>
-
<title>Page Title</title>
-
-
<meta name="viewport" content="width=device-width, initial-scale=1">
-
-
<link rel="stylesheet" href="css/jquery.mobile-1.1.1.min.css" />
-
<script src="js/jquery.js"></script>
-
<script src="js/jquery.mobile-1.1.1.min.js"></script>
-
</head>
-
<body>
-
-
<div data-role="page">
-
-
<div data-role="header">
-
<h1>Page Title</h1>
-
</div>
-
-
<div data-role="content">
-
<p>Page content goes here.</p>
-
</div>
-
-
<div data-role="footer">
-
<h4>Page Footer</h4>
-
</div>
-
</div>
-
-
</body>
-
</html>
頁面依賴的js庫、css等均放在assets目錄下,目錄組織結構如下:
運行應用後的截圖:
下面是button 的截圖,與原生控件沒什麼明顯區別,有種以假亂真的感覺:
3. 良好的用戶體驗
運行我們的應用發現,在擁有大量js的頁面被載入時,一直處於等待中,這是很糟糕的用戶體驗。可以加入進度條解決。注意到webview提供的兩個方法:setWebViewClient和setWebChromeClient。其中setWebChromeClient方法正是可以處理progress的加載,此外,還可以處理js對話框,在webview中顯示icon圖標等。對於處理progress的代碼片段如下:
-
webView.setWebChromeClient(new WebChromeClient() {
-
public void onProgressChanged(WebView view, int progress) {
-
if (progress == 100) {
-
handler.sendEmptyMessage(1);
-
}
-
super.onProgressChanged(view, progress);
-
}
-
});
其中通過handler 消息機制來處理UI線程的更新:
-
handler = new Handler() {
-
public void handleMessage(Message msg) {
-
if (!Thread.currentThread().isInterrupted()){
-
switch (msg.what) {
-
case 0:
-
pd.show();
-
break;
-
case 1:
-
pd.hide();
-
break;
-
}
-
}
-
super.handleMessage(msg);
-
}
-
};
對於setWebViewClient方法,一般用來處理html的加載(需要重載onPageStarted(WebView
view, String url, Bitmap favicon))、關閉(需要重載onPageFinished(WebViewview,
String url)方法)。
setWebViewClient和setWebChromeClient的作用:前者主要用於處理webView的控制問題,如加載、關閉、錯誤處理等;後者主要處理js對話框、圖標、頁面標題等。
4. 獲取java中的數據
單獨構建一個接口,作爲處理js與java的數據交互的橋樑,本文封裝的代碼AndroidToastForJs.java如下:
-
public class AndroidToastForJs {
-
-
private Context mContext;
-
-
public AndroidToastForJs(Context context){
-
this.mContext = context;
-
}
-
-
-
public void showToast(String toast) {
-
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
-
}
-
-
-
public int sum(int a,int b){
-
return a+b;
-
}
-
-
-
public String jsontohtml(){
-
JSONObject map;
-
JSONArray array = new JSONArray();
-
try {
-
map = new JSONObject();
-
map.put("name","aaron");
-
map.put("age", 25);
-
map.put("address", "中國上海");
-
array.put(map);
-
-
map = new JSONObject();
-
map.put("name","jacky");
-
map.put("age", 22);
-
map.put("address", "中國北京");
-
array.put(map);
-
-
map = new JSONObject();
-
map.put("name","vans");
-
map.put("age", 26);
-
map.put("address", "中國深圳");
-
map.put("phone","13888888888");
-
array.put(map);
-
} catch (JSONException e) {
-
e.printStackTrace();
-
}
-
return array.toString();
-
}
-
}
Webview提供的傳入js的方法:
-
webView.addJavascriptInterface(new AndroidToastForJs(mContext), "JavaScriptInterface");
Html頁面jsonData.html設計的部分代碼如下:
-
<script type="text/javascript">
-
var result = JavaScriptInterface.jsontohtml();
-
var obj = eval("("+result+")");//解析json字符串
-
function showAndroidToast(toast)
-
{
-
JavaScriptInterface.showToast(toast);
-
}
-
function getjsonData(){
-
var result = JavaScriptInterface.jsontohtml();
-
var obj = eval("("+result+")");//解析json字符串
-
for(i=0;i<obj.length;i++){
-
var user=obj[i];
-
document.write("<p>姓名:"+user.name+"</p>");
-
document.write("<p>年齡:"+user.age+"</p>");
-
document.write("<p>地址:"+user.address+"</p>");
-
if(user.phone!=null){
-
document.write("<p>手機號碼:"+user.address+"</p>");
-
}
-
}
-
}
-
function list(){
-
document.write("<div data-role='header'><p>another</p></div>");
-
}
-
</script>
-
</head>
-
<body>
-
<div data-role="page" >
-
<div data-role="header" data-theme="c">
-
<h1>Android via Interface</h1>
-
</div>
-
<div data-role="content">
-
<button value="say hello" onclick="showAndroidToast('Hello,Android!')" data-theme="e"></button>
-
<button value="get json data" onclick="getjsonData()" data-theme="e"></button>
-
</div>
-
<div data-role="collapsible" data-theme="c" data-content-theme="f">
-
<h3>I'm <script>document.write(obj[0].name);</script>,click to see my info</h3>
-
<p><script>document.write("<p>姓名:"+obj[0].name+"</p>");</script></p>
-
<p><script>document.write("<p>年齡:"+obj[0].age+"</p>");</script></p>
-
<p><script>document.write("<p>地址:"+obj[0].address+"</p>");</script></p>
-
</div>
-
<div data-role="footer" data-theme="c">
-
<h4>Page Footer</h4>
-
</div>
-
</div>
-
</body>
點擊say
hello按鈕運行的截圖如下:
轉自:http://blog.csdn.net/cappuccinolau/article/details/8262821/