編輯:關於Android編程
我在學習Android開發過程中遇到的第一個疑問就是Android客戶端是怎麼跟服務器數據庫進行交互的呢?這個問題是我當初初次接觸Android時所困擾我的一個很大的問題,直到幾年前的一天,我突然想到WebService是否可以呢?讓WebService充當服務器端的角色,完成與服務器數據庫操作相關的事情,而Android客戶端只要按照WebService方法參數的要求去調用就行了。在當時我對這個解決方案的實現還沒模糊,我想這個問題也是初學Android的朋友肯定會想到的問題。那麼現在就讓我們動手去實現它吧。
這個程序我們演示如何請求Web Service來獲取服務端提供的數據。
由於我對C#比較熟悉,所以我優先使用自己熟悉的技術來搭建WebService的項目。很簡單我們就用VS工具創建一個Web服務應用程序(VS2008,而從VS2010開始優先使用WCF來創建服務應用程序了,不過用WCF框架創建WebService也是很容易的)。
[WebMethod] public string DataTableTest() { DataTable dt = new DataTable(userTable); dt.Columns.Add(id,typeof(int)); dt.Columns.Add(name, typeof(string)); dt.Columns.Add(email, typeof(string)); dt.Rows.Add(1, gary.gu, [email protected]); dt.Rows.Add(2, jinyingying, [email protected]); dt.Rows.Add(3, jinyingying, [email protected]); dt.Rows.Add(4, jinyingying, [email protected]); return Util.CreateJsonParameters(dt); }這個WebService的方法很簡單,就是組建一個DataTable的數據類型,並通過CreateJsonParameters方法轉化為JSON字符串。這裡面的DataTable可以修改成從數據庫端讀取數據到DataTable對象。
public static string CreateJsonParameters(DataTable dt) { StringBuilder JsonString = new StringBuilder(); if (dt != null && dt.Rows.Count > 0) { JsonString.Append({ ); JsonString.Append(Result_List:[ ); for (int i = 0; i < dt.Rows.Count; i++) { JsonString.Append({ ); for (int j = 0; j < dt.Columns.Count; j++) { if (j < dt.Columns.Count - 1) { JsonString.Append( + dt.Columns[j].ColumnName.ToString() + : + + dt.Rows[i][j].ToString() + ,); } else if (j == dt.Columns.Count - 1) { JsonString.Append( + dt.Columns[j].ColumnName.ToString() + : + + dt.Rows[i][j].ToString() + ); } } if (i == dt.Rows.Count - 1) { JsonString.Append(} ); } else { JsonString.Append(}, ); } } JsonString.Append(]}); return JsonString.ToString(); } else { return null; } }這個方法是我從網上隨便找到的一個方法,比較土了,就是直接拼接JSON字符串(無所謂,這不是我們要關心的重點)。
WebService端准備好,就可以將其發布到IIS。發布方法跟網站一樣,如果是本機的話,可以直接測試WebService方法返回得到的結果,比如調用後會得到如下結果:
這裡肯定有人問,這外面是XML,裡面又是JSON,這不是“四不像”嗎?是的,我這樣做是想說明一點,WebService是基於Soap的,數據傳輸的格式就是XML,所以這裡得到XML文檔是理所當然。如果你想得到純淨的JSON字符串,可以使用C#中的WCF框架(可以指定客戶端返回JSON格式)或者Java中的Servlet(直接刷出JSON文本)。
好,接下來我們要做兩件事:
1、請求這個WebService得到這個JSON字符串
2、格式化這個JSON字符串在Android中顯示
我們先提供一個助手類,這是我自己動手封裝了一下這兩個操作所需要的方法。
/** * @author gary.gu 助手類 */ public final class Util { /** * @param nameSpace WS的命名空間 * @param methodName WS的方法名 * @param wsdl WS的wsdl的完整路徑名 * @param params WS的方法所需要的參數 * @return SoapObject對象 */ public static SoapObject callWS(String nameSpace, String methodName, String wsdl, MapTips:我們都知道C#中給方法加注釋,可以按3次“/”,借助於VS就可以自動生成。而在Eclipse當中,可以在方法上面輸入“/**”然後按下回車就可以自動生成。params) { final String SOAP_ACTION = nameSpace + methodName; SoapObject soapObject = new SoapObject(nameSpace, methodName); if ((params != null) && (!params.isEmpty())) { Iterator > it = params.entrySet().iterator(); while (it.hasNext()) { Map.Entry e = (Map.Entry ) it .next(); soapObject.addProperty(e.getKey(), e.getValue()); } } SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); envelope.bodyOut = soapObject; // 兼容.NET開發的Web Service envelope.dotNet = true; HttpTransportSE ht = new HttpTransportSE(wsdl); try { ht.call(SOAP_ACTION, envelope); if (envelope.getResponse() != null) { SoapObject result = (SoapObject) envelope.bodyIn; return result; } else { return null; } } catch (Exception e) { Log.e(error, e.getMessage()); } return null; } /** * * @param result JSON字符串 * @param name JSON數組名稱 * @param fields JSON字符串所包含的字段 * @return 返回List
public class TestWS extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); RelativeLayout l = new RelativeLayout(this); Button button = new Button(l.getContext()); button.setText(點擊本機webservice); l.addView(button); setContentView(l); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String nameSpace = http://tempuri.org/; final String methodName = DataTableTest; final String wsdl = http://10.77.137.119:8888/webserviceTest/Service1.asmx?WSDL; //調用WebService返回SoapObject對象 SoapObject soapObject = Util.callWS(nameSpace, methodName, wsdl, null); if (soapObject != null) { //獲得soapObject對象的DataTableTestResult屬性的值 String result = soapObject.getProperty( DataTableTestResult).toString(); Toast.makeText(TestWS.this, result, Toast.LENGTH_SHORT) .show(); try { //將JSON字符串轉換為List的結構 List> list = Util.convertJSON2List( result, Result_List, new String[] { id, name, email }); //通過Intent將List傳入到新的Activity Intent newIntent = new Intent(TestWS.this, GridViewTest.class); Bundle bundle = new Bundle(); //List一定是一個Serializable類型 bundle.putSerializable(key, (Serializable) list); newIntent.putExtras(bundle); //啟動新的Activity startActivity(newIntent); } catch (Exception e) { e.printStackTrace(); } } else { System.out.println(This is null...); } } }); } }
這裡面有兩點需要注意:
1、這個Activity並沒有加載layout布局文件,而是通過代碼創建了一個Button,這也是一種創建視圖的方法。2、通過Intent對象,我們將List
public class GridViewTest extends Activity { GridView grid; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_gridview); Intent intent = this.getIntent(); Bundle bundle = intent.getExtras(); //獲得傳進來的List先獲得傳過來的List對象,然後通過SimpleAdapter綁定到GridView。>對象 @SuppressWarnings(unchecked) List > list = (List >) bundle .getSerializable(key); //通過findViewById方法找到GridView對象 grid = (GridView) findViewById(R.id.grid01); //SimpleAdapter適配器填充 //1.context 當前上下文,用this表示,或者GridViewTest.this //2.data A List of Maps.要求是List >結構的列表,即數據源 //3.resource 布局文件 //4.from 從哪裡來,即提取數據源List中的哪些key //5.to 到哪裡去,即填充布局文件中的控件 SimpleAdapter adapter = new SimpleAdapter(this, list, R.layout.list_item, new String[] { id, name, email }, new int[] { R.id.id, R.id.name, R.id.email }); //將GridView和適配器綁定 grid.setAdapter(adapter); } }
做IOS開發的都知道,IOS提供了一個具有動態開關效果的UISwitch組件,這個組件很好用效果相對來說也很絢麗,當我們去點擊開關的時候有動畫效果,但遺憾的是Androi
activity的啟動模式一共有四種:standard、singleTop、singleTask和singleInstance,可以在AndroidMannifest.x
BroadcastReceiver,顧名思義就是“廣播接收者”的意思,它是Android四大基本組件之一,這種組件本質上是一種全局的監聽器,用於監聽系統全局的廣播消息。它
1. Java知識儲備本知識點不做重點講解:對於有基礎的同學推薦看《Java編程思想》,鞏固基礎,查漏補全,了解並熟悉更多細節知識點。對於沒有基礎的同學推薦看一本Java