Android WebView 與JS的數據交互

關於WebView

咱們知道目前android市場上的一些應用採用的開發方式大體分爲三種:Native AppWeb AppHybrid App。本文主要是Hybrid App中實現的主要技術native組件與js的數據交互的理解以及實現。javascript

 

Android API中提供了WebView組件來實現對html的渲染。所謂的HybridApp開發方式便是聚集了HTML5CSS3jS的相關開發技術,以及數據交換格式json/XML。這顯然是Web開發工程師的技能。正是由於如此,衆多中小企業選擇了這種開發方式來減小對android開發工程師的過分依賴,至於這三種開發方式的比較與優劣不在本文考慮之列。css

 

有了WebView這個組件,Android應用開發技術也就轉嫁到htmljava數據交互上來。說白了就是jsWebView的數據交互,這就是本文所要討論的。html

WebViewjs的數據交互

1.        WebView中載入靜態頁面java

 

WebView添加到應用中。和原生控件同樣,在layout引入WebView控件。代碼片斷以下:jquery

<?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>

載入頁面:android

 

webView = (WebView) findViewById(R.id.webview);
webView.loadUrl("file:///file:///android_asset/page.html");

page.html存儲在工程文件的assets根目錄下。web

2.        引入jquery mobilejson

引入js框架讓咱們編寫的html頁面更接近於原生控件的顯示效果。目前主流的移動應用js框架有:jquery mobilesencha touchjquery mobilesencha touch的選型不在本文討論範圍)。本文選擇使用jquery mobile框架

 

首先,在webview添加對js的支持:ide

WebSettings setting = webView.getSettings();
setting.setJavaScriptEnabled(true);//支持js

增長對中文的支持:

WebSettings setting = webView.getSettings();
setting.setDefaultTextEncodingName("GBK");//設置字符編碼

設置頁面滾動條風格:

webView.setScrollBarStyle(0);//滾動條風格,爲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><!-- /header -->

	<div data-role="content">	
		<p>Page content goes here.</p>		
	</div><!-- /content -->

	<div data-role="footer">
		<h4>Page Footer</h4>
	</div><!-- /footer -->
</div><!-- /page -->

</body>
</html>

頁面依賴的js庫、css等均放在assets目錄下,目錄組織結構以下:

運行應用後的截圖:

下面是button 的截圖,與原生控件沒什麼明顯區別,有種以假亂真的感受:

3.        良好的用戶體驗

運行咱們的應用發現,在擁有大量js的頁面被載入時,一直處於等待中,這是很糟糕的用戶體驗。能夠加入進度條解決。注意到webview提供的兩個方法:setWebViewClientsetWebChromeClient。其中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) {// 定義一個Handler,用於處理下載線程與UI間通信
				if (!Thread.currentThread().isInterrupted()){
					switch (msg.what) {
					case 0:
						pd.show();// 顯示進度對話框
						break;
					case 1:
						pd.hide();// 隱藏進度對話框,不可以使用dismiss()、cancel(),不然再次調用show()時,顯示的對話框小圓圈不會動。
						break;
					}
				}
				super.handleMessage(msg);
			}
		};

對於setWebViewClient方法,通常用來處理html的加載(須要重載onPageStarted(WebView view, String url, Bitmap favicon))、關閉(須要重載onPageFinishedWebViewview, String url)方法)。

 

setWebViewClientsetWebChromeClient的做用:前者主要用於處理webView的控制問題,如加載、關閉、錯誤處理等;後者主要處理js對話框、圖標、頁面標題等。

4.        獲取java中的數據

單獨構建一個接口,做爲處理jsjava的數據交互的橋樑,本文封裝的代碼AndroidToastForJs.java以下:

public class AndroidToastForJs {
	
	private Context mContext;

public AndroidToastForJs(Context context){
		this.mContext = context;
	}
	
//webview中調用toast原生組件
public void showToast(String toast) {
		Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
	}
	
//webview中求和
public int sum(int a,int b){
		return a+b;
	}
	
 //以json實現webview與js之間的數據交互
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");

   在調用的方法上必定要加上

@JavascriptInterface

android 17+以後須要加上註解纔會正常調用

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><!-- /header -->
	<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><!-- /content -->
<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><!-- /footer -->
</div><!-- /page -->
</body>

點擊say hello按鈕運行的截圖以下:

補充:webView.addJavascriptInterface(this,"Android");//this:用於調用this裏面的public方法,Android:爲調用方法的別名
this的環境下寫一個方法,必須爲public用於html調用
public void startFunction(){}

在HTML中,<a onclick="window.Android.startFunction()">點擊調用java代碼</a>
window.Android.startFunction()中的window加不加均可以,加上符合編碼規範

在java代碼中調用html中的js方法,webView.loadUrl("javascript:javacalljs("+"'hello world'"+")");//javascript:爲script標籤;在html中js方法,javacalljs:function javacalljs(str){}

相關文章
相關標籤/搜索