在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;
}
}