Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> C#程序員學習Android開發系列之調用WebService

C#程序員學習Android開發系列之調用WebService

編輯:關於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, Map 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>類型的列表,Map對應於 id:1的結構
	 */
	public static List> convertJSON2List(String result,
			String name, String[] fields) {
		List> list = new ArrayList>();
		try {
			JSONArray array = new JSONObject(result).getJSONArray(name);

			for (int i = 0; i < array.length(); i++) {
				JSONObject object = (JSONObject) array.opt(i);
				Map map = new HashMap();
				for (String str : fields) {
					map.put(str, object.get(str));
				}
				list.add(map);
			}
		} catch (JSONException e) {
			Log.e(error, e.getMessage());
		}
		return list;
	}
}
Tips:我們都知道C#中給方法加注釋,可以按3次“/”,借助於VS就可以自動生成。而在Eclipse當中,可以在方法上面輸入“/**”然後按下回車就可以自動生成。

 

 

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>傳入到了新的Activity當中,這種Intent之間的傳值方式需要注意。

 

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>對象
		@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);
	}

}
先獲得傳過來的List對象,然後通過SimpleAdapter綁定到GridView。

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved