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

來源:互聯網
上載者:User

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

我在學習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", "guwei4037@sina.com");            dt.Rows.Add(2, "jinyingying", "345822155@qq.com");            dt.Rows.Add(3, "jinyingying", "345822155@qq.com");            dt.Rows.Add(4, "jinyingying", "345822155@qq.com");            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<String, Object> params) {final String SOAP_ACTION = nameSpace + methodName;SoapObject soapObject = new SoapObject(nameSpace, methodName);if ((params != null) && (!params.isEmpty())) {Iterator<Entry<String, Object>> it = params.entrySet().iterator();while (it.hasNext()) {Map.Entry<String, Object> e = (Map.Entry<String, Object>) it.next();soapObject.addProperty(e.getKey(), e.getValue());}}SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);envelope.bodyOut = soapObject;// 相容.NET開發的Web Serviceenvelope.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<String,Object>>類型的列表,Map<String,Object>對應於 "id":"1"的結構 */public static List<Map<String, Object>> convertJSON2List(String result,String name, String[] fields) {List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();try {JSONArray array = new JSONObject(result).getJSONArray(name);for (int i = 0; i < array.length(); i++) {JSONObject object = (JSONObject) array.opt(i);Map<String, Object> map = new HashMap<String, Object>();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 {@Overrideprotected 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() {@Overridepublic 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<Map<String, Object>> list = Util.convertJSON2List(result, "Result_List", new String[] { "id","name", "email" });//通過Intent將List傳入到新的ActivityIntent newIntent = new Intent(TestWS.this,GridViewTest.class);Bundle bundle = new Bundle();//List一定是一個Serializable類型bundle.putSerializable("key", (Serializable) list);newIntent.putExtras(bundle);//啟動新的ActivitystartActivity(newIntent);} catch (Exception e) {e.printStackTrace();}} else {System.out.println("This is null...");}}});}}

這裡面有兩點需要注意:

1、這個Activity並沒有載入layout布局檔案,而是通過代碼建立了一個Button,這也是一種建立視圖的方法。

2、通過Intent對象,我們將List<Map<String,Object>>傳入到了新的Activity當中,這種Intent之間的傳值方式需要注意。

public class GridViewTest extends Activity {GridView grid;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_gridview);Intent intent = this.getIntent();Bundle bundle = intent.getExtras();//獲得傳進來的List<Map<String,Object>>對象@SuppressWarnings("unchecked")List<Map<String, Object>> list = (List<Map<String, Object>>) bundle.getSerializable("key");//通過findViewById方法找到GridView對象grid = (GridView) findViewById(R.id.grid01);//SimpleAdapter適配器填充//1.context    當前上下文,用this表示,或者GridViewTest.this//2.data       A List of Maps.要求是List<Map<String,Object>>結構的列表,即資料來源//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。

activity_gridview.xml 布局檔案:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >        <GridView         android:id="@+id/grid01"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:horizontalSpacing="1pt"        android:verticalSpacing="1pt"        android:numColumns="3"        android:gravity="center"/></LinearLayout>
list_item.xml 布局檔案:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:gravity="center_vertical"    android:orientation="vertical" >    <TextView        android:id="@+id/id"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/name"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/email"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></LinearLayout>
AndroidManifest.xml完整配置:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.webservicedemo"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="14" />    <uses-permission android:name="android.permission.INTERNET" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name=".TestWS"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <activity            android:name=".GridViewTest"            android:label="@string/app_name" >        </activity>    </application></manifest>

最終在模擬器上面顯示出了從資料庫伺服器獲得的資料:





c語言rand()函數

rand和srand的用法
首先我們要對rand&srand有個總體的看法:srand初始化隨機種子,rand產生隨機數,下面將詳細說明。

rand(產生隨機數)
表標頭檔: #include<stdlib.h>

定義函數 :int rand(void)

函數說明 :
因為rand的內部實現是用線性同餘法做的,他不是真的隨機數,只不過是因為其周期特別長,所以有一定的範圍裡可看成是隨機的,rand()會返回一隨機數值,範圍在0至RAND_MAX 間。在調用此函數產生隨機數前,必須先利用srand()設好隨機數種子,如果未設隨機數種子,rand()在調用時會自動設隨機數種子為1。rand ()產生的是假隨機數字,每次執行時是相同的。若要不同,以不同的值來初始化它.初始化的函數就是srand()。

傳回值:
返回0至RAND_MAX之間的隨機整數值,RAND_MAX的範圍最少是在32767之間(int),即雙位元組(16位元)。若用unsigned int 雙位元組是65535,四位元組是4294967295的整數範圍。
0~RAND_MAX每個數字被選中的機率是相同的。

範例:
/* 產生介於1 到10 間的隨機數值,此範例未設隨機數種子,完整的隨機數產生請參考
srand()*/
#include<stdlib.h>
main()
{
int i,j;
for(i=0;i<10;i++)
{
j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
printf("%d ",j);
}
}
執行:

9 4 8 8 10 2 4 8 3 6
9 4 8 8 10 2 4 8 3 6 //再次執行仍然產生相同的隨機數

srand(設定隨機數種子)
表標頭檔:#include<stdlib.h>

定義函數:void srand (unsigned int seed);

函數說明:
srand()用來設定rand()產生隨機數時的隨機數種子。參數seed必須是個整數,通常可以利用geypid()或time(0)的傳回值來當做seed。如果每次seed都設相同值,rand()所產生的隨機數值每次就會一樣。

範例
/* 產生介於1 到10 間的隨機數值,此範例與執行結果可與rand()參照*/
#include<time.h>
#include<stdlib.h>
main()
{
int i,j;
srand((int)time(0));
for(i=0;i<10;i++)
{
j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
printf(" %d ",j);
}
}
執行:與rand範例比較
5 8 8 8 10 2 10 8 9 9
2 9 7 4 10 3 2 10 8 7
又或:
用"int x = rand() % 100;"來產生 0 到 100 之間的隨機數這種方法是不或取的,比較好的做法是: j=(int)(n*rand()/(RAND_MAX+1.0))產生一個0到n之間的隨機數
int main(void)
{
int i;
time_t t;
srand((unsigned) time(&t));
printf("Ten r......餘下全文>>
 
c語言rand()函數

rand和srand的用法
首先我們要對rand&srand有個總體的看法:srand初始化隨機種子,rand產生隨機數,下面將詳細說明。

rand(產生隨機數)
表標頭檔: #include<stdlib.h>

定義函數 :int rand(void)

函數說明 :
因為rand的內部實現是用線性同餘法做的,他不是真的隨機數,只不過是因為其周期特別長,所以有一定的範圍裡可看成是隨機的,rand()會返回一隨機數值,範圍在0至RAND_MAX 間。在調用此函數產生隨機數前,必須先利用srand()設好隨機數種子,如果未設隨機數種子,rand()在調用時會自動設隨機數種子為1。rand ()產生的是假隨機數字,每次執行時是相同的。若要不同,以不同的值來初始化它.初始化的函數就是srand()。

傳回值:
返回0至RAND_MAX之間的隨機整數值,RAND_MAX的範圍最少是在32767之間(int),即雙位元組(16位元)。若用unsigned int 雙位元組是65535,四位元組是4294967295的整數範圍。
0~RAND_MAX每個數字被選中的機率是相同的。

範例:
/* 產生介於1 到10 間的隨機數值,此範例未設隨機數種子,完整的隨機數產生請參考
srand()*/
#include<stdlib.h>
main()
{
int i,j;
for(i=0;i<10;i++)
{
j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
printf("%d ",j);
}
}
執行:

9 4 8 8 10 2 4 8 3 6
9 4 8 8 10 2 4 8 3 6 //再次執行仍然產生相同的隨機數

srand(設定隨機數種子)
表標頭檔:#include<stdlib.h>

定義函數:void srand (unsigned int seed);

函數說明:
srand()用來設定rand()產生隨機數時的隨機數種子。參數seed必須是個整數,通常可以利用geypid()或time(0)的傳回值來當做seed。如果每次seed都設相同值,rand()所產生的隨機數值每次就會一樣。

範例
/* 產生介於1 到10 間的隨機數值,此範例與執行結果可與rand()參照*/
#include<time.h>
#include<stdlib.h>
main()
{
int i,j;
srand((int)time(0));
for(i=0;i<10;i++)
{
j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
printf(" %d ",j);
}
}
執行:與rand範例比較
5 8 8 8 10 2 10 8 9 9
2 9 7 4 10 3 2 10 8 7
又或:
用"int x = rand() % 100;"來產生 0 到 100 之間的隨機數這種方法是不或取的,比較好的做法是: j=(int)(n*rand()/(RAND_MAX+1.0))產生一個0到n之間的隨機數
int main(void)
{
int i;
time_t t;
srand((unsigned) time(&t));
printf("Ten r......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.