基於Soap協議的android客戶端和服務器的數據交互(學習天氣預報例子的心得)


    Webservice 是一種基於Soap協議的遠程調用標準,通過webservice可以將不同操作系統平臺,不同語言,不同技術整合到一起.

在PC機java客戶端,需要用一些庫來訪問webservice,可以用Ksoap第三方

的類庫來獲取服務器端webService的調用.


首先

下載Ksoap包:ksoap2-android-assembly-3.0.0-RC.4-jar-with-dependencies.jar

下載鏈接:

http://ksoap2-android.googlecode.com/svn/m2-repo/com/google/code/ksoap2-android/ksoap2-android-assembly/3.0.0/ksoap2-android-assembly-3.0.0-jar-with-dependencies.jar

新建android項目,把該包複製到該工程的src->lib目錄下.並更改工程的編譯路徑:右鍵選中工程->Properties->Java Build Path->Libraries->Add External JARs.把該包加入編譯路徑中.


七步調用WebService方法:

1 指定webService的命名空間,請求WDSL文檔的URL,調用方法名

//命名空間
	private static final String targetNameSpace="http://WebXml.com.cn/";
	//請求WSDL文檔的URL
	private static final String WSDL=
			"http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl";
	//方法名
	private static final String getSupportCity="getSupportCity";
	private static final String getWeatherbyCityName="getWeatherbyCityName";	

2 實例化SoapObject對象,如果方法有參數,傳入參數值

//實例化
SoapObject soapObject=new SoapObject(targetNameSpace, getWeatherbyCityName);

//傳入參數soapObject.addProperty(參數名, 參數值);
soapObject.addProperty("theCityName", city);


/************建議webservice的方法傳遞的參數儘量用string類型。即使是int類型,kSOAP2Java編寫的webservice也有可能交互發生異常.**************/

3 設置SOAP請求信息,把構造好的soapObject封裝進去,設置好屬性後,再發出請求

(參數部分爲SOAP協議版本號,與webservice版本號一致)

SoapSerializationEnvelope envelope=new SoapSerializationEnvelope(SoapEnvelope.VER11);
    	envelope.bodyOut=soapObject;
    	envelope.dotNet=true;
    	envelope.setOutputSoapObject(soapObject);
    	/*
    	 *  注意:這個屬性是對dotnetwebservice協議的支持,
    	 *  如果dotnet的webservice 不指定rpc方式則用true否則要用false 
    	*/

/*****************

常量SoapEnvelope.VER10:對應於SOAP1.0規範
常量SoapEnvelope.VER11:對應於SOAP1.1規範
常量SoapEnvelope.VER12:對應於SOAP1.2規範

***********************/

/**********************

在kSOAP中,我們用Base64把二進制流編碼爲ASCII字符串,這樣就可以通過XML/SOAP傳輸二進制數據了。
org.ksoap2.serialization.MarshalBase64的目的就是,把SOAP XML中的xsd:based64Binary元素序列化爲Java字節數組(byete array)類型。類似的,kSOAP2還提供了MarshalDate、MarshalHashtable類來把相應的元素序列化爲Java的Date、Hashtable類型。

                (該步可省 據需要決定)   (new MarshalBase64()).register(envelope); //註冊envelope

*********************/

4 構建傳輸對象,開啓調試信息

HttpTransportSE httpTranstation=new HttpTransportSE(WSDL);
    	httpTranstation.debug=true;
/*********如果HttpTransport的debug屬性爲true,那麼此時就可以通過System.out.println("Response dump>>+ tx.responseDump);
打印出HttpTransport的調試信息。尤其當前面call方法和getResult方法發生異常時,這個調試信息是非常有用的。************/

/***************

對於HttpTransport的處理上,kSOAP2和kSOAP1.2的寫法不一樣。
   kSOAP 1.2,HttpTransport的構造函數是HttpTransport (String url, String soapAction),第二個參數soapAction可以是要調用的webservice方法名。
   kSOAP 2,構造函數是 HttpTransport(String url)。kSOAP2相當於把webservice方法名分離出去,完全交給SoapObject去封裝,而HttpTransport僅僅負責把SoapEnvelope發送出去並接收響應,這樣更合理一些。

***************/

調用WebService(其中參數爲1:命名空間+方法名稱,2:Envelope對象):

httpTranstation.call(targetNameSpace+getWeatherbyCityName, envelope);

/*************方法HttpTransport.call()自己就能夠發送請求給服務器、接收服務器響應並序列化SOAP消息,如下所示:

ht.call(soapAction, envelope);

soapAction – SOAP 規範定義了一個名爲 SOAPAction 的新 HTTP 標頭,所有 SOAP HTTP 請求(即使是空的)都必須包含該標頭。 

                    soapAction標頭旨在表明該消息的意圖。通常可以置此參數爲null,這樣HttpTransport就會設置HTTP標頭SOAPAction爲空字符串。

Envelope – 就是前面我們構造好的SoapSerializationEnvelope或SoapEnvelope對象。

*************/


解析返回數據:

SoapObject result=(SoapObject)envelope.getResponse();
//打印出調試錯誤信息System.out.println("Responsedump>>"+ tx.responseDump);

/********

由於HttpTransport類實際上是調用了HttpConnection作網絡連接,所以必須另起一個線程來專門做kSOAP工作,否則會堵塞操作。

********/


7 對result進行提取和處理便於顯示.


示例>天氣預報獲取城市天氣情況和圖標

public class WebServiceUtil {
	//命名空間
	private static final String targetNameSpace="http://WebXml.com.cn/";
	//請求WSDL文檔的URL
	private static final String WSDL=
			"http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl";
	//方法名
	private static final String getSupportCity="getSupportCity";
	private static final String getWeatherbyCityName="getWeatherbyCityName";	

/***************************
     * 根據城市信息獲取天氣預報信息
     * @param city
     * @return
     ***************************/
    public WeatherBean getWeatherByCity(String city){
    	WeatherBean bean=new WeatherBean();
    	//實例化SoapObject對象,如果方法有參數,傳入參數值
    	SoapObject soapObject=new SoapObject(
    			targetNameSpace, getWeatherbyCityName);
    	soapObject.addProperty("theCityName", city);
    	
    	SoapSerializationEnvelope envelope=new SoapSerializationEnvelope(SoapEnvelope.VER11);
    	envelope.bodyOut=soapObject;
    	/*
    	 *  注意:這個屬性是對dotnetwebservice協議的支持,
    	 *  如果dotnet的webservice 不指定rpc方式則用true否則要用false 
    	envelope.dotNet=true;
    	envelope.setOutputSoapObject(soapObject);
    	*/
    	HttpTransportSE httpTranstation=new HttpTransportSE(WSDL);
    	httpTranstation.debug=true;
    	try{
    		httpTranstation.call(
    				targetNameSpace+getWeatherbyCityName, envelope);
    		SoapObject result=(SoapObject)envelope.getResponse();
    		//對getWeatherbyCityName返回的XML文件進行解析,提取三天天氣情況給bean
    		bean=parserWeather(result);
    	}catch (IOException e){
    		e.printStackTrace();
    	}catch (XmlPullParserException e){
    		e.printStackTrace();
    	}
    	return bean;
    }
    /**
     * 解析返回的結果(從soapObject對今天\明天\後天三天的天氣情況的獲取)
     * @param soapObject
     */
    protected WeatherBean parserWeather(SoapObject soapObject){
    	WeatherBean bean=new WeatherBean();
    	List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();
    	Map<String,Object>map=new HashMap<String,Object>();
    	// 城市名---xml文件第二個參數
    	bean.setCityName(soapObject.getProperty(1).toString());
    	//城市情況 ---位於最後一個參數
    	bean.setCityDescription(soapObject.getProperty(soapObject.getPropertyCount()-1).toString());
    	//天氣實況+建議
    	bean.setLiveWeather(soapObject.getProperty(10).toString()+"\n"+soapObject.getProperty(11).toString());
    	//其他數據
        //把三天天氣情況載入數組,打包進入bean.setList();
    	String date=soapObject.getProperty(6).toString();
    	
    	String weatherToday="今天:"+date.split(" ")[0];
    	weatherToday+="\n天氣:"+date.split(" ")[1];
    	weatherToday+="\n氣溫:"+soapObject.getProperty(5).toString();
        weatherToday+="\n風力:"+soapObject.getProperty(7).toString();
        weatherToday+="\n";
        
       // List<Integer> icons=new ArrayList<Integer>();
        //天氣趨勢開始圖片名稱(以下稱:圖標一),天氣趨勢結束圖片名稱(以下稱:圖標二)
        //icons.add(parseIcon(soapObject.getProperty(8).toString()));//Adds the specified object at the end of this List
       // icons.add(parseIcon(soapObject.getProperty(9).toString()));
        int icon1_ID=parseIcon(soapObject.getProperty(8).toString());
        int icon2_ID=parseIcon(soapObject.getProperty(9).toString());
       // Log.v("icon1",soapObject.getProperty(8).toString());
       // Log.v("icon2",soapObject.getProperty(9).toString());
        map.put("weatherDay",weatherToday);
        //map.put("icons", icons);
        map.put("icon1", icon1_ID);
        map.put("icon2", icon2_ID);
        list.add(map);
        //-------------------------------------
        map=new HashMap<String,Object>(); 
        date=soapObject.getProperty(13).toString();
        String weatherTomorrow="明天:" + date.split(" ")[0];  
        weatherTomorrow+="\n天氣:"+ date.split(" ")[1]; 
        weatherTomorrow+="\n氣溫:"+soapObject.getProperty(12).toString();
        weatherTomorrow+="\n風力:"+soapObject.getProperty(14).toString();
        weatherTomorrow+="\n";
        
        //icons=new ArrayList<Integer>();
         
       // icons.add(parseIcon(soapObject.getProperty(15).toString()));      
        //icons.add(parseIcon(soapObject.getProperty(16).toString()));
        icon1_ID=parseIcon(soapObject.getProperty(15).toString());
        icon2_ID=parseIcon(soapObject.getProperty(16).toString());
        Log.v("icon1",soapObject.getProperty(15).toString());
        Log.v("icon2",soapObject.getProperty(16).toString());
        map.put("weatherDay", weatherTomorrow);
        map.put("icon1", icon1_ID);
        map.put("icon2", icon2_ID);
        //map.put("icons",icons);
        list.add(map);
        
        //------------------------
        map=new HashMap<String,Object>(); 
        
        date=soapObject.getProperty(18).toString();
        String weatherAfterTomorrow="後天:" + date.split(" ")[0];  
        weatherAfterTomorrow+="\n天氣:"+ date.split(" ")[1]; 
        weatherAfterTomorrow+="\n氣溫:"+soapObject.getProperty(17).toString();
        weatherAfterTomorrow+="\n風力:"+soapObject.getProperty(19).toString();
        weatherAfterTomorrow+="\n";
        
       // icons=new ArrayList<Integer>();
       // icons.add(parseIcon(soapObject.getProperty(20).toString()));      
        //icons.add(parseIcon(soapObject.getProperty(21).toString()));
        icon1_ID=parseIcon(soapObject.getProperty(20).toString());
        icon2_ID=parseIcon(soapObject.getProperty(21).toString());
        Log.v("icon1",soapObject.getProperty(20).toString());
        Log.v("icon2",soapObject.getProperty(21).toString());
        map.put("weatherDay", weatherAfterTomorrow);
        map.put("icon1", icon1_ID);
        map.put("icon2", icon2_ID);
      
        //map.put("icons",icons);
        list.add(map); 
        //------------------------------------
        bean.setList(list);
        return bean;
        
    }
    //解析圖標名稱.gif字符串強制轉化爲--R.drawable.c_1整型 便於查表
    
    private int parseIcon(String strIcon){
    	if (strIcon == null)
			return -1;
		if ("0.gif".equals(strIcon))
			return R.drawable.a_0;
		if ("1.gif".equals(strIcon))
			return R.drawable.a_1;
		if ("2.gif".equals(strIcon))
			return R.drawable.a_2;
		if ("3.gif".equals(strIcon))
			return R.drawable.a_3;
		if ("4.gif".equals(strIcon))
			return R.drawable.a_4;
		if ("5.gif".equals(strIcon))
			return R.drawable.a_5;
		if ("6.gif".equals(strIcon))
			return R.drawable.a_6;
		if ("7.gif".equals(strIcon))
			return R.drawable.a_7;
		if ("8.gif".equals(strIcon))
			return R.drawable.a_8;
		if ("9.gif".equals(strIcon))
			return R.drawable.a_9;
		if ("10.gif".equals(strIcon))
			return R.drawable.a_10;
		if ("11.gif".equals(strIcon))
			return R.drawable.a_11;
		if ("12.gif".equals(strIcon))
			return R.drawable.a_12;
		if ("13.gif".equals(strIcon))
			return R.drawable.a_13;
		if ("14.gif".equals(strIcon))
			return R.drawable.a_14;
		if ("15.gif".equals(strIcon))
			return R.drawable.a_15;
		if ("16.gif".equals(strIcon))
			return R.drawable.a_16;
		if ("17.gif".equals(strIcon))
			return R.drawable.a_17;
		if ("18.gif".equals(strIcon))
			return R.drawable.a_18;
		if ("19.gif".equals(strIcon))
			return R.drawable.a_19;
		if ("20.gif".equals(strIcon))
			return R.drawable.a_20;
		if ("21.gif".equals(strIcon))
			return R.drawable.a_21;
		if ("22.gif".equals(strIcon))
			return R.drawable.a_22;
		if ("23.gif".equals(strIcon))
			return R.drawable.a_23;
		if ("24.gif".equals(strIcon))
			return R.drawable.a_24;
		if ("25.gif".equals(strIcon))
			return R.drawable.a_25;
		if ("26.gif".equals(strIcon))
			return R.drawable.a_26;
		if ("27.gif".equals(strIcon))
			return R.drawable.a_27;
		if ("28.gif".equals(strIcon))
			return R.drawable.a_28;
		if ("29.gif".equals(strIcon))
			return R.drawable.a_29;
		if ("30.gif".equals(strIcon))
			return R.drawable.a_30;
		if ("31.gif".equals(strIcon))
			return R.drawable.a_31;
		return 0;
	}
  }

界面設計如ListVIew應用一所示http://blog.csdn.net/lilysea2012/article/details/8648027

AndroidManifest.xml文件添加這一行

<uses-permission android:name="android.permission.INTERNET"/>

效果如下












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章