基于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"/>

效果如下












评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值