在Android中使用SOAP调用Webservice
介绍
如果使用SOAP进行访问Webservice。
什么是SOAP
SOAP(Simple Object Access Protocol)简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息。
WebService三要素:SOAP、WSDL (Web Services Description Language)、UDDI( Universal Description Discovery and Integration ), SOAP用来传递信息的格式, WSDL 用来描述如何访问具体的接口, UDDI用来管理,分发,查询webService 具体实现可以搜索 Web Services简单实例 ; SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议(HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。它还支持从消息系统到远程过程调用(RPC)等大量的应用程序。SOAP使用基于XML的数据结构和超文本传输协议(HTTP)的组合定义了一个标准的方法来使用Internet上各种不同操作环境中的分布式对象。
以下为SOAP封装结构:
概述
对于Android访问远端的web Service,除了官方标准JSR 172,我们还有两种选择:
— KSOAP2
— Wingfoot
Wingfoot是由Wingfoot Software (www.wingfoot.com)出品的一款J2ME(CLDC/CDC) SOAP1.1的轻量级实现方案。
KSOAP是Enhydra.org的一个开源作品,是EnhydraME项目的一部分。基于Enhydra.org出品的开源通用XML解析器kXML,kSOAP完成了J2ME/MIDP平台上的SOAP解析和调用工作。
Stefan Haustein领导的KSOAP开发小组于2001年5月17日推出了Alhpa版本。之后又经过了一年的开发,2002年6月6日推出的kSOAP 1.2支持了SOAP1.2规范。2003年8月25日推出的kSOAP2,对SOAP序列化规范支持得更好了。
KSOAP2下载提示:
http://code.google.com/p/ksoap2-android/
KSOAP2改进了对Microsoft dotNET的兼容。现在也相对比较有影响力。
使用类来访问Webservice
1.org.ksoap2.serialization.SoapObject
SOAP结构的封装类。
方法
返回值 |
方法名 |
描述 |
SoapObject |
addProperty(String name, Object value) |
添加请求Webservice的参数 |
Object |
getProperty(int index) |
返回指定节点数据 |
int |
getPropertyCount() |
返回节点的条数 |
int |
getAttributeCount() |
节点属性个数 |
Object |
getAttribute(int index) |
返回指定属性的值 |
2. org.ksoap2.serialization.SoapSerializationEnvelope
属性
类型 |
属性名 |
描述 |
Boolean |
dotNet |
设置此变量为true兼容.Net-Services的默认编码 |
方法
返回值 |
方法名 |
描述 |
void |
setOutputSoapObject(java.lang.Object soapObject) |
分配对象的信封作为soap调用出站消息 |
3.org.ksoap2.transport.HttpTransportSE
方法
返回值 |
方法名 |
描述 |
void |
call(java.lang.String SoapAction, SoapEnvelope envelope) |
结合HTTP协议进行请求 |
KSOAP2提供了以下几种规范:
常量SoapEnvelope.VER10:对应于SOAP 1.0规范
常量SoapEnvelope.VER11:对应于SOAP 1.1规范
常量SoapEnvelope.VER12:对应于SOAP 1.2规范
SOAP信封结构:
测试:
一、新建一个SOAP的Android项目。
二、将ksoap2-android-assembly-3.1.1-jar-with-dependencies.jar引用到第三方库中,以便为项目提供服务器。
三、测试。
3.1 使用.net创建一个本地WebService,请求返回HelloWord
package com.fighter.test;
import java.util.Date;
import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.HttpTransportSE;
import android.test.AndroidTestCase;
public class Test extends AndroidTestCase{
public void testSOAP(){ final String NAME_SPACE = "http://tempuri.org/"; final String SOAP_ACTION = "http://tempuri.org/HelloWorld"; final String URL = "http://192.168.1.190:8081/Service1.asmx"; final String METHOD = "HelloWorld";
SoapObject request = new SoapObject(NAME_SPACE, METHOD); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapSerializationEnvelope.VER11); envelope.setOutputSoapObject(request); envelope.dotNet = true; System.out.println("开始请求时间..." + new Date()); HttpTransportSE transport = new HttpTransportSE(URL); transport.debug = true; try { transport.call(SOAP_ACTION, envelope); } catch (Exception e) { System.out.println("请求错误."); }
if (envelope.bodyIn != null) { System.out.println("1--------:"); SoapObject result1 = (SoapObject) envelope.bodyIn; for (int i = 0; i < result1.getAttributeCount(); i++) { System.out.println("对应的键:" + result1.getAttributeAsString(i)); } for (int i = 0; i < result1.getPropertyCount(); i++) { System.out.println("\t " + result1.getProperty(i).toString()); } }
System.out.println("请求结束:" + new Date()); } }
|
响应结果:
|
3.2使用公用Webservice进行测试。
地址:http://webservice.webxml.com.cn
测试根据省级编号查找市级信息。
Wsdl:http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
四川省id:31123
方法名:getSupportCityDataset
请求和响应的格式
测试代码:
static final String TAG = "SOAP_TEST"; // 获取城市列表 public void testGetSupportCityDataset() { final String CITY_ID = "31123"; // 四川id final String NAME_SPACE = "http://WebXml.com.cn/"; final String SAOP_ACTION = "http://WebXml.com.cn/getSupportCityDataset"; final String URL = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx"; final String METHOD = "getSupportCityDataset"; SoapObject request = new SoapObject(NAME_SPACE, METHOD); request.addProperty("theRegionCode", CITY_ID); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); envelope.setOutputSoapObject(request); envelope.dotNet = true; HttpTransportSE transport = new HttpTransportSE(URL); try { transport.debug = true; transport.call(SAOP_ACTION, envelope); // Log.v(TAG, "request:" + transport.requestDump); // Log.v(TAG, "response:" + transport.responseDump); } catch (Exception e) { Log.e(TAG, "response错误", e); } SoapObject response = (SoapObject) envelope.bodyIn; if (response != null) { // Log.v(TAG, "返回数据:" + response.toString()); SoapObject result = (SoapObject) response.getProperty(0); Log.v(TAG, "result 节点数:" + result.getPropertyCount()); // SoapObject dataSet = (SoapObject) result.getProperty(0); // Log.v(TAG, "显示数据:" + dataSet.getPropertyAsString(0)); // SoapObject schema = (SoapObject) result.getProperty("schema"); // Log.v(TAG, "schema id = " + schema.getAttribute("id")); if (result.getPropertyCount() >= 2) { SoapObject diffgram = (SoapObject) result.getProperty(1); if (diffgram.getPropertyCount() >= 1) { SoapObject region = (SoapObject) diffgram.getProperty(0); for (int i = 0; i < region.getPropertyCount(); i++) { try { Log.d(TAG, "" + City.parse((SoapObject) region .getProperty(i))); } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "错误", e); } } } } } } static class City { String id; String rowOrder; int cityId; String cityName; static City parse(SoapObject cityElement) throws Exception { City city = new City(); try { city.id = cityElement.getAttributeAsString("id"); city.rowOrder = cityElement.getAttributeAsString("rowOrder"); city.cityId = Integer.parseInt(cityElement .getPropertyAsString("CityID")); city.cityName = cityElement.getPropertyAsString("CityName"); } catch (Exception e) { throw e; } return city; } @Override public String toString() { return "id:" + id + "\n" + "rowOrder:" + rowOrder + "\n" + cityId + " - " + cityName; } }