Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android使用工具類輕松實現通過WebService進行網絡編程

Android使用工具類輕松實現通過WebService進行網絡編程

編輯:Android開發實例

相信大家在平常的開發中,對網絡的操作用到HTTP協議比較多,通過我們使用Get或者Post的方法調用一個數據接口,然後服務器給我們返回JSON格式的數據,我們解析JSON數據然後展現給用戶,相信很多人很喜歡服務器給我們返回JSON數據格式,因為他解析方便,也有一些JSON的解析庫,例如Google提供的GSON,阿裡巴巴的FastJson,不過還是推薦大家使用FastJson來解析,我自己開發中也是用FastJson來解析,FastJson的介紹http://code.alibabatech.com/wiki/display/FastJSON/Home ,不過有時候我們用到WebService接口來獲取數據, WebService是一種基於SOAP協議的遠程調用標准,通過webservice可以將不同操作系統平台、不同語言、不同技術整合到一塊。在Android SDK中並沒有提供調用WebService的庫,因此,需要使用第三方的SDK來調用WebService。PC版本的WEbservice客戶端庫非常豐富,例如Axis2,CXF等,但這些開發包對於Android系統過於龐大,也未必很容易移植到Android系統中。因此,這些開發包並不是在我們的考慮范圍內。適合手機的WebService客戶端的SDK有一些,比較常用的有Ksoap2,可以從http://code.google.com/p/ksoap2-android/wiki/HowToUse?tm=2 進行下載,將jar包加入到libs目錄下就行了,接下來帶大家來調用WebService接口

首先我們新建一個工程,取名WebServiceDemo,我們從http://www.webxml.com.cn/zh_cn/web_services.aspx 來獲取WebService接口,這裡面有一些免費的WebService接口,我們就用裡面的天氣接口吧http://www.webxml.com.cn/WebServices/WeatherWebService.asmx

我們新建一個WebService的工具類,用於對WebService接口的調用,以後遇到調用WebService直接拷貝來用就行了

  1. package com.example.webservicedemo;  
  2.  
  3. import java.io.IOException;  
  4. import java.util.HashMap;  
  5. import java.util.Iterator;  
  6. import java.util.Map;  
  7. import java.util.concurrent.ExecutorService;  
  8. import java.util.concurrent.Executors;  
  9.  
  10. import org.ksoap2.SoapEnvelope;  
  11. import org.ksoap2.serialization.SoapObject;  
  12. import org.ksoap2.serialization.SoapSerializationEnvelope;  
  13. import org.ksoap2.transport.HttpResponseException;  
  14. import org.ksoap2.transport.HttpTransportSE;  
  15. import org.xmlpull.v1.XmlPullParserException;  
  16.  
  17. import android.os.Handler;  
  18. import android.os.Message;  
  19.  
  20. /**  
  21.  * 訪問WebService的工具類,  
  22.  *     
  23.  *   
  24.  * @author xiaanming  
  25.  *   
  26.  */ 
  27. public class WebServiceUtils {  
  28.     public static final String WEB_SERVER_URL = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx";  
  29.       
  30.       
  31.     // 含有3個線程的線程池  
  32.     private static final ExecutorService executorService = Executors  
  33.             .newFixedThreadPool(3);  
  34.  
  35.     // 命名空間  
  36.     private static final String NAMESPACE = "http://WebXml.com.cn/";  
  37.  
  38.     /**  
  39.      *   
  40.      * @param url  
  41.      *            WebService服務器地址  
  42.      * @param methodName  
  43.      *            WebService的調用方法名  
  44.      * @param properties  
  45.      *            WebService的參數  
  46.      * @param webServiceCallBack  
  47.      *            回調接口  
  48.      */ 
  49.     public static void callWebService(String url, final String methodName,  
  50.             HashMap<String, String> properties,  
  51.             final WebServiceCallBack webServiceCallBack) {  
  52.         // 創建HttpTransportSE對象,傳遞WebService服務器地址  
  53.         final HttpTransportSE httpTransportSE = new HttpTransportSE(url);  
  54.         // 創建SoapObject對象  
  55.         SoapObject soapObject = new SoapObject(NAMESPACE, methodName);  
  56.  
  57.         // SoapObject添加參數  
  58.         if (properties != null) {  
  59.             for (Iterator<Map.Entry<String, String>> it = properties.entrySet()  
  60.                     .iterator(); it.hasNext();) {  
  61.                 Map.Entry<String, String> entry = it.next();  
  62.                 soapObject.addProperty(entry.getKey(), entry.getValue());  
  63.             }  
  64.         }  
  65.  
  66.         // 實例化SoapSerializationEnvelope,傳入WebService的SOAP協議的版本號  
  67.         final SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(  
  68.                 SoapEnvelope.VER11);  
  69.         // 設置是否調用的是.Net開發的WebService  
  70.         soapEnvelope.setOutputSoapObject(soapObject);  
  71.         soapEnvelope.dotNet = true;  
  72.         httpTransportSE.debug = true;  
  73.  
  74.         // 用於子線程與主線程通信的Handler  
  75.         final Handler mHandler = new Handler() {  
  76.  
  77.             @Override 
  78.             public void handleMessage(Message msg) {  
  79.                 super.handleMessage(msg);  
  80.                 // 將返回值回調到callBack的參數中  
  81.                 webServiceCallBack.callBack((SoapObject) msg.obj);  
  82.             }  
  83.  
  84.         };  
  85.  
  86.         // 開啟線程去訪問WebService  
  87.         executorService.submit(new Runnable() {  
  88.  
  89.             @Override 
  90.             public void run() {  
  91.                 SoapObject resultSoapObject = null;  
  92.                 try {  
  93.                     httpTransportSE.call(NAMESPACE + methodName, soapEnvelope);  
  94.                     if (soapEnvelope.getResponse() != null) {  
  95.                         // 獲取服務器響應返回的SoapObject  
  96.                         resultSoapObject = (SoapObject) soapEnvelope.bodyIn;  
  97.                     }  
  98.                 } catch (HttpResponseException e) {  
  99.                     e.printStackTrace();  
  100.                 } catch (IOException e) {  
  101.                     e.printStackTrace();  
  102.                 } catch (XmlPullParserException e) {  
  103.                     e.printStackTrace();  
  104.                 } finally {  
  105.                     // 將獲取的消息利用Handler發送到主線程  
  106.                     mHandler.sendMessage(mHandler.obtainMessage(0,  
  107.                             resultSoapObject));  
  108.                 }  
  109.             }  
  110.         });  
  111.     }  
  112.  
  113.     /**  
  114.      *   
  115.      *   
  116.      * @author xiaanming  
  117.      *   
  118.      */ 
  119.     public interface WebServiceCallBack {  
  120.         public void callBack(SoapObject result);  
  121.     }  
  122.  

我們通過調用裡面的callWebService(String url, final String methodName,HashMap<String, String> properties,final WebServiceCallBack webServiceCallBack)就可以來獲取我們想要的數據,現在講解下裡面的實現思路

 

  • 創建HttpTransportsSE對象。通過HttpTransportsSE類的構造方法可以指定WebService的WSDL文檔的URL
  • 創建SoapObject對象,裡面的參數分別是WebService的命名空間和調用方法名
  • 設置調用方法的參數值,如果沒有參數,就不設置,有參數的話調用SoapObject對象的addProperty(String name, Object value)方法將參數加入到SoapObject對象中
  • 實例化SoapSerializationEnvelope,傳入WebService的SOAP協議的版本號,將上面的SoapObject對象通過setOutputSoapObject(Object soapObject)設置到裡面,並設置是否調用的是.Net開發的WebService和是否debug等信息
  • 因為涉及到網絡操作,所以我們使用了線程池來異步操作調用WebService接口,我們在線程中調用HttpTransportsSE對象的call(String soapAction, SoapEnvelope envelope)方法就能實現對WebService的調用,並且通過soapEnvelope.bodyIn獲取WebService返回的信息,但是返回的信息是在子線程中,我們需要利用Handler來實現子線程與主線程進行轉換,然後在Handler的handleMessage(Message msg)中將結果回調到callBack的參數中,總體思路就是這個樣子,接下來我們來使用這個工具類吧

我們先用一個ListView來顯示所有的省份,然後點擊每個省進去到市。市也用一個ListView來顯示,最後點擊市用TextView來顯示獲取的WebService天氣情況,思路很簡單

用來顯示省份的布局,裡面只有一個ListView

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.     xmlns:tools="http://schemas.android.com/tools" 
  3.     android:layout_width="match_parent" 
  4.     android:layout_height="match_parent" > 
  5.  
  6.     <ListView 
  7.         android:id="@+id/province_list" 
  8.         android:layout_width="match_parent" 
  9.         android:layout_height="wrap_content" 
  10.         android:cacheColorHint="@android:color/transparent" 
  11.         android:fadingEdge="none" > 
  12.     </ListView> 
  13.  
  14. </RelativeLayout> 

接下來就是Activity的代碼,先用工具類調用WebService方法,然後在回調方法callBack(SoapObject result)中解析數據到一個List<String>中,在設置ListView的適配器

  1. package com.example.webservicedemo;  
  2.  
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.  
  6. import org.ksoap2.serialization.SoapObject;  
  7.  
  8. import android.app.Activity;  
  9. import android.content.Intent;  
  10. import android.os.Bundle;  
  11. import android.view.View;  
  12. import android.widget.AdapterView;  
  13. import android.widget.AdapterView.OnItemClickListener;  
  14. import android.widget.ArrayAdapter;  
  15. import android.widget.ListView;  
  16. import android.widget.Toast;  
  17.  
  18. import com.example.webservicedemo.WebServiceUtils.WebServiceCallBack;  
  19.  
  20. /**  
  21.  * 顯示天氣省份的Activity  
  22.  *     
  23.  *   
  24.  * @author xiaanming  
  25.  *  
  26.  */ 
  27. public class MainActivity extends Activity {  
  28.     private List<String> provinceList = new ArrayList<String>();  
  29.  
  30.     @Override 
  31.     public void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.activity_main);  
  34.         init();  
  35.     }  
  36.  
  37.     private void init() {  
  38.         final ListView mProvinceList = (ListView) findViewById(R.id.province_list);  
  39.           
  40.         //顯示進度條  
  41.         ProgressDialogUtils.showProgressDialog(this, "數據加載中...");  
  42.           
  43.         //通過工具類調用WebService接口  
  44.         WebServiceUtils.callWebService(WebServiceUtils.WEB_SERVER_URL, "getSupportProvince", null, new WebServiceCallBack() {  
  45.               
  46.             //WebService接口返回的數據回調到這個方法中  
  47.             @Override 
  48.             public void callBack(SoapObject result) {  
  49.                 //關閉進度條  
  50.                 ProgressDialogUtils.dismissProgressDialog();  
  51.                 if(result != null){  
  52.                     provinceList = parseSoapObject(result);  
  53.                     mProvinceList.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, provinceList));  
  54.                 }else{  
  55.                     Toast.makeText(MainActivity.this, "獲取WebService數據錯誤", Toast.LENGTH_SHORT).show();  
  56.                 }  
  57.             }  
  58.         });  
  59.           
  60.         mProvinceList.setOnItemClickListener(new OnItemClickListener() {  
  61.  
  62.             @Override 
  63.             public void onItemClick(AdapterView<?> parent, View view,  
  64.                     int position, long id) {  
  65.                 Intent intent = new Intent(MainActivity.this, CityActivity.class);  
  66.                 intent.putExtra("province", provinceList.get(position));  
  67.                 startActivity(intent);  
  68.                   
  69.             }  
  70.         });  
  71.           
  72.           
  73.     }  
  74.       
  75.     /**  
  76.      * 解析SoapObject對象  
  77.      * @param result  
  78.      * @return  
  79.      */ 
  80.     private List<String> parseSoapObject(SoapObject result){  
  81.         List<String> list = new ArrayList<String>();  
  82.         SoapObject provinceSoapObject = (SoapObject) result.getProperty("getSupportProvinceResult");  
  83.         if(provinceSoapObject == null) {  
  84.             return null;  
  85.         }  
  86.         for(int i=0; i<provinceSoapObject.getPropertyCount(); i++){  
  87.             list.add(provinceSoapObject.getProperty(i).toString());  
  88.         }  
  89.           
  90.         return list;  
  91.     }  
  92.  

點擊省份進入該省份下面的市。也用一個ListView來顯示市的數據,布局跟上面一樣,Activity裡面的代碼也差不多相似,我就不過多說明了,直接看代碼

  1. package com.example.webservicedemo;  
  2.  
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6.  
  7. import org.ksoap2.serialization.SoapObject;  
  8.  
  9. import android.app.Activity;  
  10. import android.content.Intent;  
  11. import android.os.Bundle;  
  12. import android.view.View;  
  13. import android.widget.AdapterView;  
  14. import android.widget.AdapterView.OnItemClickListener;  
  15. import android.widget.ArrayAdapter;  
  16. import android.widget.ListView;  
  17. import android.widget.Toast;  
  18.  
  19. import com.example.webservicedemo.WebServiceUtils.WebServiceCallBack;  
  20.  
  21. /**  
  22.  * 顯示城市的Activity  
  23.  *     
  24.  *   
  25.  * @author xiaanming  
  26.  *  
  27.  */ 
  28. public class CityActivity extends Activity {  
  29.     private List<String> cityStringList;  
  30.  
  31.     @Override 
  32.     public void onCreate(Bundle savedInstanceState) {  
  33.         super.onCreate(savedInstanceState);  
  34.         setContentView(R.layout.activity_main);  
  35.         init();  
  36.     }  
  37.  
  38.     private void init() {  
  39.         final ListView mCityList = (ListView) findViewById(R.id.province_list);  
  40.           
  41.         //顯示進度條  
  42.         ProgressDialogUtils.showProgressDialog(this, "數據加載中...");  
  43.           
  44.         //添加參數  
  45.         HashMap<String, String> properties = new HashMap<String, String>();  
  46.         properties.put("byProvinceName", getIntent().getStringExtra("province"));  
  47.           
  48.         WebServiceUtils.callWebService(WebServiceUtils.WEB_SERVER_URL, "getSupportCity", properties, new WebServiceCallBack() {  
  49.               
  50.             @Override 
  51.             public void callBack(SoapObject result) {  
  52.                 ProgressDialogUtils.dismissProgressDialog();  
  53.                 if(result != null){  
  54.                     cityStringList = parseSoapObject(result);  
  55.                     mCityList.setAdapter(new ArrayAdapter<String>(CityActivity.this, android.R.layout.simple_list_item_1, cityStringList));  
  56.                 }else{  
  57.                     Toast.makeText(CityActivity.this, "獲取WebService數據錯誤", Toast.LENGTH_SHORT).show();  
  58.                 }  
  59.             }  
  60.         });  
  61.           
  62.         mCityList.setOnItemClickListener(new OnItemClickListener() {  
  63.  
  64.             @Override 
  65.             public void onItemClick(AdapterView<?> parent, View view,  
  66.                     int position, long id) {  
  67.                 Intent intent = new Intent(CityActivity.this, WeatherActivity.class);  
  68.                 intent.putExtra("city", cityStringList.get(position));  
  69.                 startActivity(intent);  
  70.             }  
  71.         });  
  72.     }  
  73.       
  74.     /**  
  75.      * 解析SoapObject對象  
  76.      * @param result  
  77.      * @return  
  78.      */ 
  79.     private List<String> parseSoapObject(SoapObject result){  
  80.         List<String> list = new ArrayList<String>();  
  81.         SoapObject provinceSoapObject = (SoapObject) result.getProperty("getSupportCityResult");  
  82.         for(int i=0; i<provinceSoapObject.getPropertyCount(); i++){  
  83.             String cityString = provinceSoapObject.getProperty(i).toString();  
  84.             list.add(cityString.substring(0, cityString.indexOf("(")).trim());  
  85.         }  
  86.           
  87.         return list;  
  88.     }  

接下來就是點擊相對應的城市調用WebService接口來獲取該城市下面的天氣詳情啦,為了簡單起見,我用一個TextView來顯示天氣信息,因為天氣信息很多,一個屏幕顯示不完,所以我們考慮在外面加一個ScrollView來進行滾動

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="fill_parent" 
  4.     android:layout_height="fill_parent" > 
  5.  
  6.     <ScrollView 
  7.         android:layout_width="fill_parent" 
  8.         android:layout_height="fill_parent" > 
  9.  
  10.         <LinearLayout 
  11.             android:layout_width="match_parent" 
  12.             android:layout_height="match_parent" > 
  13.  
  14.             <TextView 
  15.                 android:id="@+id/weather" 
  16.                 android:textColor="#336598" 
  17.                 android:textSize="16sp" 
  18.                 android:layout_width="match_parent" 
  19.                 android:layout_height="match_parent" /> 
  20.         </LinearLayout> 
  21.     </ScrollView> 
  22.  
  23. </RelativeLayout> 

Activity的代碼就不做過多說明,跟上面的大同小異

 

  1. package com.example.webservicedemo;  
  2.  
  3. import java.util.HashMap;  
  4.  
  5. import org.ksoap2.serialization.SoapObject;  
  6.  
  7. import android.app.Activity;  
  8. import android.os.Bundle;  
  9. import android.widget.TextView;  
  10. import android.widget.Toast;  
  11.  
  12. import com.example.webservicedemo.WebServiceUtils.WebServiceCallBack;  
  13.  
  14. /**  
  15.  * 顯示天氣的Activity  
  16.  *     
  17.  *   
  18.  * @author xiaanming  
  19.  *  
  20.  */ 
  21. public class WeatherActivity extends Activity{  
  22.     @Override 
  23.     public void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         setContentView(R.layout.weather_layout);  
  26.         init();  
  27.     }  
  28.  
  29.     private void init() {  
  30.         final TextView mTextWeather = (TextView) findViewById(R.id.weather);  
  31.         ProgressDialogUtils.showProgressDialog(this, "數據加載中...");  
  32.         HashMap<String, String> properties = new HashMap<String, String>();  
  33.         properties.put("theCityName", getIntent().getStringExtra("city"));  
  34.           
  35.         WebServiceUtils.callWebService(WebServiceUtils.WEB_SERVER_URL, "getWeatherbyCityName", properties, new WebServiceCallBack() {  
  36.               
  37.             @Override 
  38.             public void callBack(SoapObject result) {  
  39.                 ProgressDialogUtils.dismissProgressDialog();  
  40.                 if(result != null){  
  41.                     SoapObject detail = (SoapObject) result.getProperty("getWeatherbyCityNameResult");  
  42.                     StringBuilder sb = new StringBuilder();  
  43.                     for(int i=0; i<detail.getPropertyCount(); i++){  
  44.                         sb.append(detail.getProperty(i)).append("\r\n");  
  45.                     }  
  46.                     mTextWeather.setText(sb.toString());  
  47.                 }else{  
  48.                     Toast.makeText(WeatherActivity.this, "獲取WebService數據錯誤", Toast.LENGTH_SHORT).show();  
  49.                 }  
  50.             }  
  51.         });  
  52.     }  

到這裡我們就完成了編碼工作,在運行程序之前我們需要在AndroidManifest.xml注冊Activity,以及添加訪問網絡的權限

  1. <application 
  2.         android:icon="@drawable/ic_launcher" 
  3.         android:label="@string/app_name" 
  4.         android:theme="@style/AppTheme" > 
  5.         <activity 
  6.             android:name="com.example.webservicedemo.MainActivity" 
  7.             android:label="@string/title_activity_main" > 
  8.             <intent-filter> 
  9.                 <action android:name="android.intent.action.MAIN" /> 
  10.  
  11.                 <category android:name="android.intent.category.LAUNCHER" /> 
  12.             </intent-filter> 
  13.         </activity> 
  14.         <activity android:name=".CityActivity"/> 
  15.         <activity android:name=".WeatherActivity"></activity> 
  16.     </application> 
  17.       
  18.     <uses-permission android:name="android.permission.INTERNET"/> 

運行結果:

 

 

 

 

省份,城市列表可以加上A-Z的排序功能,可以參考下http://www.fengfly.com/plus/view-214530-1.html,我這裡就不添加了,需要添加的朋友自行實現

源碼下載

 

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