趁热打铁,通过两天的不懈努力,终于小有成就。总算通过自建webservice服务端与Android客户端实现了自定义类即复杂对象的传递。
一、服务器端:
使用XFire引擎创建Webservice,方法很简单,网上也有许多例子,不再赘述。代码目录结构如下:
IBusLocationService为接口类,BusLocationServiceImpl为实现类。CBusLocation为自定义类,即要传递的类型。IBusLocationService.aegis.xml为XFire的映射配置文件。CFinalData为自己写的辅助类,不用关心。
二、客户端:
不要忘记引入Jar包(ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar)。代码目录结构如下:
MainActivity_BusLocation为Activity类。MainActivity为另一个Activity,调用网络webservice查询天气应用,不用关心。MarshalDouble是为了实现Double类序列化的类。CBusLocation为客户端的自定义类型,与服务器端的自定义类型相对。
1.CBusLocation类源码:
package com.jianboBusLocation.entity.sub;
import java.util.Hashtable;
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import java.lang.Double;
public class CBusLocation implements KvmSerializable{
/**
*
*/
public static Class CBUSLOCATION_CLASS = CBusLocation.class;
private int iDataNum;
private Double dBusLatitude;
private Double dBusLongitude;
public static final String NAMESPACE = "http://entity.jianboBusLocation.com";
public CBusLocation(){}
public CBusLocation(int iDataNum, Double dLatitude, Double dLongitude){
this.iDataNum = iDataNum;
this.dBusLatitude = dLatitude;
this.dBusLongitude = dLongitude;
}
/*
public CBusLocation(SoapObject obj){
this.iDataNum = Integer.parseInt(obj.getProperty("iDataNum").toString());
this.dBusLatitude = Double.parseDouble(obj.getProperty("dBusLatitude").toString());
this.dBusLongitude = Double.parseDouble(obj.getProperty("dBusLongitude").toString());
}
*/
@Override
public Object getProperty(int arg0) {
// TODO Auto-generated method stub
switch(arg0){
case 2:
return iDataNum;
case 1:
return dBusLongitude;
case 0:
return dBusLatitude;
}
return null;
}
@Override
public int getPropertyCount() {
// TODO Auto-generated method stub
return 3;
}
@Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo info) {
// TODO Auto-generated method stub
switch(arg0){
case 2:
info.type=PropertyInfo.INTEGER_CLASS;//设置info type的类型
info.name="iDataNum";
info.namespace = NAMESPACE;
break;
case 1:
info.type=Double.class;
info.name="dBusLongitude";
info.namespace = NAMESPACE;
break;
case 0:
info.type=Double.class;
info.name="dBusLatitude";
info.namespace = NAMESPACE;
break;
default:
break;
}
}
@Override
public void setProperty(int index, Object value) {
// TODO Auto-generated method stub
switch(index){
case 2:
iDataNum = Integer.valueOf(value.toString());
break;
case 1:
dBusLongitude = Double.valueOf(value.toString());
break;
case 0:
dBusLatitude = Double.valueOf(value.toString());
break;
default:
break;
}
}
public int getIDataNum() {
return iDataNum;
}
public void setIDataNum(int iDataNum) {
this.iDataNum = iDataNum;
}
public double getDBusLatitude() {
return dBusLatitude;
}
public void setDBusLatitude(Double dBusLatitude) {
this.dBusLatitude = dBusLatitude;
}
public double getDBusLongitude() {
return dBusLongitude;
}
public void setDBusLongitude(Double dBusLongitude) {
this.dBusLongitude = dBusLongitude;
}
}
一定要实现接口KvmSerializable,并注意NameSpace属性。
2.MainActivity_BusLocation中调用webservice的方法源码:
public void getRemoteInfo_My(String phoneSec) throws SoapFault {
// 命名空间
String nameSpace = "http://jianboBusLocation.com";
// 调用的方法名称
String methodName = "getBusLocation";
// EndPoint
String endPoint = "http://192.168.0.7:8088/BusLocationService/services/BusLocationService";
// SOAP Action
String soapAction = "http://jianboBusLocation.com/getBusLocation";
// 指定WebService的命名空间和调用的方法名
SoapObject rpc = new SoapObject(nameSpace, methodName);
// 设置需调用WebService接口需要传入的两个参数mobileCode、userId
//rpc.addProperty("in0", "my test");
rpc.addProperty("iTime", 1);
CBusLocation cTemp = new CBusLocation();
cTemp.setIDataNum(2);
cTemp.setDBusLatitude(2.0);
cTemp.setDBusLongitude(2.0);
PropertyInfo objekt = new PropertyInfo();
objekt.setName("inBusLoc");
objekt.setValue(cTemp);
objekt.setType(cTemp.getClass());
objekt.setNamespace(CBusLocation.NAMESPACE);
rpc.addProperty(objekt);
// 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10);
envelope.bodyOut = rpc;
// 设置是否调用的是dotNet开发的WebService
envelope.dotNet = false;
envelope.encodingStyle="UTF-8";
// 等价于envelope.bodyOut = rpc;
envelope.setOutputSoapObject(rpc);
envelope.addMapping("http://entity.jianboBusLocation.com", "CBusLocation", CBusLocation.CBUSLOCATION_CLASS);
//Marshal class
MarshalDouble marshaldDouble = new MarshalDouble();
marshaldDouble.register(envelope);
HttpTransportSE transport = new HttpTransportSE(endPoint);
transport.debug = true;
try {
// 调用WebService
transport.call(soapAction, envelope);
} catch (Exception e) {
e.printStackTrace();
}
// 获取返回的数据
SoapObject object = (SoapObject) envelope.getResponse();
//CBusLocation cLoc = new CBusLocation(object);
// 获取返回的结果
//2个数,1经度,0纬度
resultString = "latitude : " + object.getProperty(0).toString()
+ "\nlongitude : " + object.getProperty(1).toString()
+ "\ndata number : " + object.getProperty(2).toString();
}
注意
参数设置,及addMapping方法的调用。addMapping方法的第一个参数为服务器端的自定义类的命名空间,第二个参数为类名,第三个参数为客户端自定义类。
以上,这样就完成了。看似简单,可是费了我两三天的时间,追根究底还是自己懂得太少,写出来希望对大家有用。
由于项目需要使用webservice与android所以学习了一下。期间遇到了许多问题,最大的收获就是,信心与坚持。有信心,相信自己能够解决问题;坚持住,遇到困难不退缩。电子信息技术如浩瀚大海,咱们做开发的,不可能什么技术都会,只有不断学习才能跟上技术发展。向所有程序猿致敬,信心与坚持,与君共勉!
借鉴文章:怎样通过ksoap2发送复杂参数给web service方法(How to send complex type using ksoap2)