Ksoap 使用簡介

轉:http://www.open-open.com/bbs/view/1320111271749?sort=newestjava

 

 

 

WebService 是一種基於SOAP協議的遠程調用標準。經過WebService能夠將不一樣操做系統平臺,不一樣語言、不一樣技術整合到一塊兒。在Android SDK中並無提供調用WebService的庫,所以,須要使用第三方類庫(KSOAP2)來調用WebService。在本文將介紹在Android 中調用WebService的具體細節,並在最後給出一個完整的例子來演示如何使用KSOAP2來調用WebService。android

 

安裝第三方類庫:KSOAP2
        PC版本的WebService客戶端類庫很是豐富,例如,Axis二、CXF等,但這些類庫對於Android系統過於龐大,也未必很容易移植到 Android系統上。所以,這些開發包並不在咱們考慮的範圍內。適合手機的WebService客戶端類庫也有一些。本例使用了比較經常使用的 KSOAP2。讀者能夠從以下的地址下載Android版的KSOAP2。

 
       將下載後的jar文件複製到Eclipse工程的lib目錄中(若是沒有該目錄,能夠新建一個,固然,也能夠放在其餘的目錄中)。並在Eclipse工程中引用這個jar包,引用後的Eclipse工程目錄結構如圖1所示。
圖1 引用KSOAP2開發包
 
使用KSOAP2調用WebService
       讀者可按以下6步來調用WebService的方法。
1. 指定WebService的命名空間和調用的方法名,代碼以下:
1 SoapObject request = new SoapObject("http://service", "getName");
    SoapObject類的第1個參數表示WebService的命名空間,能夠從WSDL文檔中找到WebService的命名空間。第2個參數表示要調用的WebService方法名。
 
2. 設置調用方法的參數值,這一步是可選的,若是方法沒有參數,能夠省略這一步。設置方法的參數值的代碼以下:
1 request.addProperty("param1", "value1"); 
2 request.addProperty("param2", "value2");
   要注意的是,addProperty方法的第1個參數雖然表示調用方法的參數名,但該參數值並不必定與服務端的WebService類中的方法參數名一致,只要設置參數的順序一致便可。
 
3. 生成調用WebService方法的SOAP請求信息。該信息由SoapSerializationEnvelope對象描述,代碼以下:
1 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
2 envelope.bodyOut = request;
 
      建立SoapSerializationEnvelope對象時須要經過SoapSerializationEnvelope類的構造方法設置SOAP協 議的版本號。該版本號須要根據服務端WebService的版本號設置。在建立SoapSerializationEnvelope對象後,不要忘了設置 SoapSerializationEnvelope類的bodyOut屬性,該屬性的值就是在第1步建立的SoapObject對象。
 
4. 建立HttpTransportSE對象。經過HttpTransportSE類的構造方法能夠指定WebService的WSDL文檔的URL,代碼以下:
1 HttpTransportSE ht =  
2     new HttpTransportSE("http://192.168.17.156:8080/axis2/services/SearchProductService?wsdl");
5. 使用call方法調用WebService方法,代碼以下:
 
1 ht.call(null, envelope);
call方法的第1個參數通常爲null,第2個參數就是在第3步建立的SoapSerializationEnvelope對象。
 
6. 使用getResponse方法得到WebService方法的返回結果,代碼以下:
1 SoapObject soapObject = (SoapObject) envelope.getResponse();
示例:經過WebService查詢產品信息
        本例涉及到一個WebService服務端程序和一個OPhone客戶端程序。讀者可直接將服務端程序(axis2目錄)複製到<Tomcat安裝目錄>\webapps目錄中,而後啓動Tomcat,並在瀏覽器地址欄中輸入以下的URL:
http://localhost:8080/axis2
 
        若是在瀏覽器中顯示如圖2所示的頁面,說明服務端程序已經安裝成功。
surface view2.png
圖2 WebService主頁面
 
        這個服務端WebService程序是SearchProductService,實際上SearchProductService是一個Java類,只 是利用Axis2將其映射成WebService。在該類中有一個getProduct方法。這個方法有一個String類型的參數,表示產品名稱。該方 法返回一個Product對象,該對象有3個屬性:name、price和productNumber。讀者可使用以下的URL來查看 SearchProductService的WSDL文檔。
http://localhost:8080/axis2/services/SearchProductService?wsdl
 
       顯示WSDL文檔的頁面如圖3所示。
surface view3.png
圖3 WSDL文檔
 
         在圖3中的黑框中就是WebService的命名空間,也是SoapObject類的構造方法的第1個參數值。這個WebService程序能夠直接使用以下的URL進行測試。
http://localhost:8080/axis2/services/SearchProductService/getProduct?param0=iphone
 
        測試的結果如圖4所示。
surface view4.png
圖4 測試getProduct方法
 
        從圖4所示的測試結果能夠看出,Axis2將getProduct方法返回的Product對象直接轉換成了XML文檔(其實是SOAP格式)返回。
 
       下面咱們來根據前面介紹的使用KSOAP2的步驟來編寫調用WebService的OPhone客戶端程序,代碼以下:
01 package net.blogjava.mobile.wsclient; 
02     
03 import org.ksoap2.SoapEnvelope; 
04 import org.ksoap2.serialization.SoapObject; 
05 import org.ksoap2.serialization.SoapSerializationEnvelope; 
06 import org.ksoap2.transport.HttpTransportSE; 
07 import android.app.Activity; 
08 import android.os.Bundle; 
09 import android.view.View; 
10 import android.view.View.OnClickListener; 
11 import android.widget.Button; 
12 import android.widget.EditText; 
13 import android.widget.TextView; 
14     
15 public class Main extends Activity implements OnClickListener 
16
17     @Override 
18     public void onClick(View view) 
19     
20         EditText etProductName = (EditText)findViewById(R.id.etProductName); 
21         TextView tvResult = (TextView)findViewById(R.id.tvResult); 
22         // WSDL文檔的URL,192.168.17.156爲PC的ID地址 
23         String serviceUrl = "http://192.168.17.156:8080/axis2/services/SearchProductService?wsdl"
24         // 定義調用的WebService方法名 
25         String methodName = "getProduct"
26         // 第1步:建立SoapObject對象,並指定WebService的命名空間和調用的方法名 
27         SoapObject request = new SoapObject("http://service", methodName); 
28         // 第2步:設置WebService方法的參數 
29         request.addProperty("productName", etProductName.getText().toString()); 
30         // 第3步:建立SoapSerializationEnvelope對象,並指定WebService的版本 
31         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
32         // 設置bodyOut屬性 
33         envelope.bodyOut = request; 
34         // 第4步:建立HttpTransportSE對象,並指定WSDL文檔的URL 
35         HttpTransportSE ht = new HttpTransportSE(serviceUrl);         
36         try 
37         {  
38             // 第5步:調用WebService 
39             ht.call(null, envelope); 
40             if (envelope.getResponse() != null
41             
42                 // 第6步:使用getResponse方法得到WebService方法的返回結果 
43                 SoapObject soapObject = (SoapObject) envelope.getResponse(); 
44                 // 經過getProperty方法得到Product對象的屬性值 
45                 String result = "產品名稱:" + soapObject.getProperty("name") + "\n"
46                 result += "產品數量:" + soapObject.getProperty("productNumber") + "\n"
47                 result += "產品價格:" + soapObject.getProperty("price"); 
48                 tvResult.setText(result); 
49     
50             
51             else 
52                 tvResult.setText("無此產品."); 
53             
54         
55         catch (Exception e) 
56         
57         
58     
59     @Override 
60     public void onCreate(Bundle savedInstanceState) 
61     
62         super.onCreate(savedInstanceState); 
63         setContentView(R.layout.main); 
64         Button btnSearch = (Button) findViewById(R.id.btnSearch); 
65         btnSearch.setOnClickListener(this); 
66     
67 }
   在編寫上面代碼時應注意以下兩點:
 
  • 在 第2步中addProperty方法的第1個參數值是productName,該值雖然是getProduct方法的參數名,但addProperty方 法的第1個參數值並不限於productName,讀者能夠將這個參數設爲其餘的任何字符串(但該值必須在XML中是合法的,例如,不是設爲 「<」、「>」等XML預留的字符串)。
  • 經過SoapObject類的getProperty方法能夠得到Product對象的屬性值,這些屬性名就是圖4所示的測試結果中的屬性名。
        運行本例,在文本框中輸入「htc hero」,單擊【查詢】按鈕,會在按鈕下方顯示如圖5所示的查詢結果。
 
surface view5.png
圖5  顯示查詢結果
防止UI組件阻塞
        從功能上看,本文示例中給出的代碼並無任何問題。但可能有的讀者會有這樣的擔憂:若是調用WebService的用戶不少,至使服務端響應遲緩;或服務 端的IP根本就不對,那麼在這些狀況下,用戶界面的按鈕和文本框組件豈不是象「死」了同樣沒法響應用戶的其餘動做。固然,發生這種狀況的可能性是有的,尤 其是在複雜的網絡環境中發生的可能性是很大的,一但發生這種事情,就會使整個軟件系統在用戶體驗上變得很是糟糕。
用戶和開發人員都但願改善這種糟糕的狀況。最理想的狀態是單擊按鈕調用WebService方法時,即便因爲某種緣由,WebService方法並未當即返回,界面上的組件仍然會處於活動狀態,也就是說,用戶仍然可使用當前界面中的其餘組件。
 
         在OPhone中能夠採用異步的方式來達到這個目的。異步實際上就是經過多線程的方式來實現。通常使用new Thread(this).start()來建立和開始一個線程。但本節並不使用Thread來實現異步,而是經過AsyncTask類使要執行的任務 (調用WebService)在後臺執行。
 
        下面先看看改進後的代碼。
 
01 package net.blogjava.mobile.wsclient; 
02     
03 import org.ksoap2.SoapEnvelope; 
04 import org.ksoap2.serialization.SoapObject; 
05 import org.ksoap2.serialization.SoapSerializationEnvelope; 
06 import org.ksoap2.transport.HttpTransportSE; 
07 import android.app.Activity; 
08 import android.os.AsyncTask; 
09 import android.os.Bundle; 
10 import android.view.View; 
11 import android.view.View.OnClickListener; 
12 import android.widget.Button; 
13 import android.widget.EditText; 
14 import android.widget.TextView; 
15     
16 public class Main extends Activity implements OnClickListener 
17
18     private EditText etProductName; 
19     private TextView tvResult; 
20     
21     class WSAsyncTask extends AsyncTask 
22     
23         String result = ""
24         @Override 
25         protected Object doInBackground(Object... params) 
26         
27             try 
28             
29                 String serviceUrl = "http://192.168.17.156:8080/axis2/services/SearchProductService?wsdl"
30                 String methodName = "getProduct"
31                 SoapObject request = new SoapObject("http://service"
32                         methodName); 
33                 request.addProperty("productName", etProductName.getText().toString()); 
34                 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( 
35                         SoapEnvelope.VER11); 
36                 envelope.bodyOut = request; 
37                 HttpTransportSE ht = new HttpTransportSE(serviceUrl); 
38     
39                 ht.call(null, envelope); 
40                 if (envelope.getResponse() != null
41                 
42                     SoapObject soapObject = (SoapObject) envelope.getResponse(); 
43                     result = "產品名稱:" + soapObject.getProperty("name") + "\n"
44                     result += "產品數量:" + soapObject.getProperty("productNumber"
45                             + "\n"
46                     result += "產品價格:" + soapObject.getProperty("price"); 
47     
48                 
49                 else 
50                 
51                     result = "無此產品."
52                 
53             
54             catch (Exception e) 
55             
56                 result = "調用WebService錯誤."
57             
58             // 必須使用post方法更新UI組件 
59             tvResult.post(new Runnable() 
60             
61                 @Override 
62                 public void run() 
63                 
64                     tvResult.setText(result); 
65     
66                 
67             }); 
68             return null
69         
70     
71     
72     @Override 
73     public void onClick(View view) 
74
75     // 異步執行調用WebService的任務   
76         new WSAsyncTask().execute(); 
77     
78     @Override 
79     public void onCreate(Bundle savedInstanceState) 
80     
81         super.onCreate(savedInstanceState); 
82         setContentView(R.layout.main); 
83         Button btnSearch = (Button) findViewById(R.id.btnSearch); 
84         btnSearch.setOnClickListener(this); 
85         etProductName = (EditText) findViewById(R.id.etProductName); 
86         tvResult = (TextView) findViewById(R.id.tvResult); 
87     
88     
89 }
     調用WebService的核心代碼與示例中的代碼徹底同樣,在這裏就再也不作具體的介紹了。但在編寫上面的代碼時還須要注意以下幾點。
 
1. 通常須要編寫一個AsyncTask的子類來完成後臺執行任務的工做。
2.  AsyncTask的核心方法是doInBackground,當調用AsyncTask類的execute方法時,doInBackground方法會異步執行。所以,能夠將執行任務的代碼寫在doInBackground方法中。
3. 由 於本例中的TextView組件是在主線程(UI線程)中建立的,所以,在其餘的線程(doInBackground方法所在的線程)中不能直接更新 TextVew組件。爲了更新TextView組件,須要使用TextView類的post方法。該方法的參數是一個Runnable對象,須要將更新 TextView組件的代碼寫在Runnable接口的run方法中。
4. 雖然不能在其餘線程中更新UI組件,但能夠從其餘線程直接讀取UI組件的值。例如,在doInBackground方法中直接讀取了EditText組件的值。
5. 調用AsyncTask類的execute方法後會當即返回。execute方法的參數就是doInBackground方法的參數。doInBackground方法的返回值能夠經過AsyncTask.execute(...).get()方法得到。
讀者能夠將本例中的IP改爲其餘的值,看看單擊按鈕後,是否還可在文本框中輸入其餘的內容。若是這個IP是正確的,而且WebService可訪問,那麼會在TextView組件中輸出相應的返回值。
 
總結
       本文主要介紹瞭如何使用KSOAP2來調用WebService。KSOAP2是第三方開發的專門用於在移動設備調用WebService的類庫。使用 KSOAP2調用WebService可分爲6步來完成,其中主要使用了SoapObject對象來指定了要調用的方法,而後經過 HttpTransportSE對象的call方法來調用WebService的方法,最後經過getResponse方法返回結果。讀者能夠經過本文提 供的完整示例來體會使用KSOAP2調用WebService的完整過程。在最後還介紹瞭如何經過異步調用WebService的方式來防止因服務端故障 或其餘緣由致使的UI組件阻塞。
相關文章
相關標籤/搜索