以前主要作客戶端UI交互,不多處理數據和接觸服務端,但如今的移動設備根本不可能離得開網絡鏈接,數據的交換。最近學習的是在android端如何去調用遠程WebService,都說WebService是一種基於SOAP協議的遠程調用標準,對於這個協議理解不深,知道webservice能夠將不一樣操做系統平臺、不一樣語言、不一樣技術整合到一塊,android SDK沒有直接調用webservice的庫,最經常使用的是藉助ksoap2-android這個第三方SDK,點擊打開連接,而後和其餘第三方jar包同樣導入android項目中便可。java
對於WebService服務器具體的編寫,現階段本身不瞭解,暫且使用網絡免費的WebService進行學習http://www.webxml.com.cn/zh_cn/index.aspx,利用這個來寫一個簡單的國內天氣預報的查詢,代碼編寫參照《瘋狂Android講義》相關部分,本身作部分修改。android
-------------------------------------------------------------------------------------------------------------web
如下是幾個主要的方法:安全
1.建立HttpTransportSE傳輸對象:HttpTransportSE ht = new HttpTransportSE(SERVICE_URL); SERVICE_URL是webservice提供服務的url服務器
2.使用SOAP1.1協議建立Envelop對象:SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 設置SOAP協議的版本號,根據服務端WebService的版本號設置。網絡
3.實例化SoapObject對象:SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName); 第一個參數表示WebService的命名空間,能夠從WSDL文檔中找到WebService的命名空間。第二個參數表示要調用的WebService方法名。多線程
4.設置調用方法的參數值,若是沒有參數,能夠省略:例如soapObject.addProperty("theCityCode", cityName);異步
5.記得設置bodyout屬性 envelope.bodyOut = soapObject;ide
6.調用webservice:ht.call(SERVICE_NAMESPACE+methodName, envelope);svn
7.獲取服務器響應返回的SOAP消息:
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName+"Result");
-------------------------------------------------------------------------------------------------------------
在這個天氣預報的demo中須要屢次調用webservice,將方法寫在一個工具類中,代碼以下:
package com.example.webservicedemo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
public class WebServiceUtil {
// 定義webservice的命名空間
public static final String SERVICE_NAMESPACE = "http://WebXml.com.cn/";
// 定義webservice提供服務的url
public static final String SERVICE_URL = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx";
// 調用遠程webservice獲取省份列表
public static List<String> getProvinceList() {
// 調用 的方法
String methodName = "getRegionProvince";
// 建立HttpTransportSE傳輸對象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
try {
ht.debug = true;
// 使用SOAP1.1協議建立Envelop對象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
// 實例化SoapObject對象
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE,
methodName);
envelope.bodyOut = soapObject;
// 設置與.NET提供的webservice保持較好的兼容性
envelope.dotNet = true;
// 調用webservice
ht.call(SERVICE_NAMESPACE + methodName, envelope);
if (envelope.getResponse() != null) {
// 獲取服務器響應返回的SOAP消息
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
// 解析服務器響應的SOAP消息
return parseProvinceOrCity(detail);
}
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 根據省份獲取城市列表
public static List<String> getCityListsByProvince(String province) {
// 調用的方法
String methodName = "getSupportCityString";
// 建立httptransportSE傳輸對象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;
// 實例化SoapObject對象
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName);
// 添加一個請求參數
soapObject.addProperty("theRegionCode", province);
// 使用soap1.1協議建立envelop對象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.bodyOut = soapObject;
// 設置與.NET提供的webservice保持較好的兼容性
envelope.dotNet = true;
// 調用webservice
try {
ht.call(SERVICE_NAMESPACE + methodName, envelope);
if (envelope.getResponse() != null) {
// 獲取服務器響應返回的SOAP消息
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
// 解析服務器響應的SOAP消息
return parseProvinceOrCity(detail);
}
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 解析省份或城市
public static List<String> parseProvinceOrCity(SoapObject detail) {
ArrayList<String> result = new ArrayList<String>();
for (int i = 0; i < detail.getPropertyCount(); i++) {
// 解析出每一個省份
result.add(detail.getProperty(i).toString().split(",")[0]);
}
return result;
}
// 根據城市字符串獲取相應天氣狀況
public static SoapObject getWeatherByCity(String cityName) {
String methodName = "getWeather";
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName);
soapObject.addProperty("theCityCode", cityName);
envelope.bodyOut = soapObject;
envelope.dotNet = true;
try {
ht.call(SERVICE_NAMESPACE + methodName, envelope);
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
return detail;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
上面這個即是主要實現遠程調用webservice的代碼,其餘實如今activity中完成便可,可是這裏也會涉及到一個問題,就是Android多線程問題,在調用webservice時,爲了防止ANR的出現,不能在主線程中進行,須要另開子線程執行,,由於子線程涉及到UI更新,Android主線程是線程不安全的,也就是說,更新UI只能在主線程中更新,子線程中操做是危險的.便要涉及Handler的使用了,實在是不才,本身更多時候習慣使用AsyncTask來代替Handler(仍是要從新琢磨下Handler的使用方法),由於操做起來比較簡單方便,下面是項目中異步操做類中的一個:
package com.example.webservicedemo;
import java.util.List;
import android.os.AsyncTask;
import android.widget.Spinner;
public class ProvinceAsyncTask extends AsyncTask<String, String, List<String>> {
private MainActivity activity;
private List<String> provinces;
private Spinner sp_province;
public ProvinceAsyncTask (MainActivity activity,Spinner sp_province){
this.activity = activity;
this.sp_province = sp_province;
}
@Override
protected List<String> doInBackground(String... params) {
// TODO Auto-generated method stub
provinces = WebServiceUtil.getProvinceList();
return null;
}
@Override
protected void onPostExecute(List<String> result) {
// TODO Auto-generated method stub
ListAdapter adapter = new ListAdapter(activity, provinces);
sp_province.setAdapter(adapter);
}
}
能夠看出來比較簡單,在doInBackground中執行調用webservice,在onPostExecute中執行列表刷新展現
最後附上該demo的代碼,但願能夠對初涉及android調用webservice的朋友有幫助