Ksoap-android 编程案例
移动端编程在工作中,也会遇到android与webservice之间的通信, 为了更好的兼容安卓端通信,有大神写了一个框架Ksoap-android, 使得安卓通webservice 通信变得简单。
但是实际编程中也并不是那么简单,会遇到各种奇葩的问题。但是网上查找信息时会发现,基本都是入门级的代码,不能解决实际 问题。比如android端请求一个复杂的一个结构体,或结构体中还有结构体,或都 数组之类的问题。
我经过了一个大晚上研究把问题解决了, 记录到博客,以备自己下次学习,如果何可以帮助其它人解决问题那就更好啦, 知识就是用来分享的。
用案例解释更直接 ,不想那么多文字,直接上代码:
案例就搞最复杂的, webservice一个方法接收两个结构体: 第一个比较 简单的结构体Person, 第二个是含有结构体数组的结构 体City(含有Person结构体)
实体类一定要重写 setter和getter 方法,不会webserice会读取不到值。
实体类: Person.java
public class Person implements KvmSerializable {
private String Name;
public void setName(String name) {
Name = name;
}
public String getName() {
return Name;
}
@Override
public Object getProperty(int i) {
Object object = null;
switch (i) {
case 0:
object = this.Name;
break;
}
return object;
}
@Override
public int getPropertyCount() {
return 1;
}
@Override
public void setProperty(int i, Object o) {
switch (i) {
case 0:
Name = o.toString();
break;
}
}
@Override
public void getPropertyInfo(int i, Hashtable hashtable, PropertyInfo propertyInfo) {
switch (i) {
case 0:
propertyInfo.name = "Name";
propertyInfo.type = PropertyInfo.STRING_CLASS;
break;
}
}
}
要实现接口KvmSerializable , 现在是一个属性, 看下规则就知道 ,如果是两个属性那就 加上每个方法 添加到 case 1; 并且grePropertyCount return 2; 以此类推。就是一个完整的实体类了。
City.java
public class City implements KvmSerializable {
private String Name;
private PersonArraySerializer PersonList;
public void setName(String name) {
Name = name;
}
public String getName() {
return Name;
}
public PersonArraySerializer getPersonList() {
return PersonList;
}
public void setPersonList(PersonArraySerializer personList) {
PersonList = personList;
}
@Override
public Object getProperty(int i) {
Object object = null;
switch (i) {
case 0:
object = this.Name;
break;
case 1:
object = this.PersonList;
break;
}
return object;
}
@Override
public int getPropertyCount() {
return 2;
}
@Override
public void setProperty(int i, Object o) {
switch (i) {
case 0:
Name = o.toString();
break;
case 1:
PersonList = (PersonArraySerializer) o;
break;
}
}
@Override
public void getPropertyInfo(int i, Hashtable hashtable, PropertyInfo propertyInfo) {
switch (i) {
case 0:
propertyInfo.name = "Name";
propertyInfo.type = PropertyInfo.STRING_CLASS;
break;
case 1:
propertyInfo.name = "PersonList";
propertyInfo.type = PropertyInfo.VECTOR_CLASS;
break;
}
}
}
之后,Ksoap也是不支持数组的,要重新写一个数组的类 这里我重新写了一个PersonArraySerializer 的数组类
PersonArraySerializer.java
public class PersonArraySerializer extends Vector<Person> implements KvmSerializable {
@Override
public Object getProperty(int index) {
return this.get(index);
}
@Override
public int getPropertyCount() {
return this.size();
}
@Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
info.name = "Person";
// info.name = "operation";
info.type = Person.class;
}
@Override
public void setProperty(int index, Object arg1) {
this.add((Person) arg1);
}
}
下面是请求步骤:
public void requestSoap() {
//创建请求,参数分别为Web服务访问地址、调用的方法,此处调用的是插入日志方法,需要传入一个日志对象
SoapObject request = new SoapObject("http://tempuri.org/","Do_Hanger_Record");//此处的url即为wsdl中的targetNamespace,和调用的方法
Person person = new Person(); //创建一个person对象
person.setName("aaa");
City c = new City(); //创建一个含有person数组的对象
c.setName("tz");
PersonArraySerializer persons = new PersonArraySerializer();
persons.add(person);
persons.add(person);
c.setPersonList(persons);
PropertyInfo propertyInfo = new PropertyInfo(); //设置结构体person到request中
propertyInfo.setName("person"); //webservice的接收的参数
propertyInfo.setValue(person); //发送的实体类
propertyInfo.setType(Person.class); //设置结构体的类型
request.addProperty(propertyInfo); //设置到请求中
PropertyInfo propertyInfo1 = new PropertyInfo(); //设置结构体city到request中
propertyInfo1.setName("c");
propertyInfo1.setValue(c);
propertyInfo1.setType(City.class);
request.addProperty(propertyInfo1);
HttpTransportSE httpTransportSE = new HttpTransportSE("http://192.168.221.185:8913/WebService1.asmx"); //设置webserice的URL
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
envelope.addMapping("http://tempuri.org/", "Person", Person.class); //增加person的映射让webservices可以实别(只要自定义类型都要写上映射)
envelope.addMapping("http://tempuri.org/", "City", City.class);
envelope.addMapping("http://tempuri.org/", "PersonArraySerializer", PersonArraySerializer.class);
try {
//提交
httpTransportSE.call(null, envelope);
if (envelope.getResponse() != null) {
Log.I("Ksoap",envelope.getResponse()==null?"null":envelope.getResponse().toString());
messageCallback.showText(envelope.getResponse().toString());
} else {
Log.I("Ksoap","null");
}
messageCallback.hideProgressDlg();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
注释很详细,应该差不多啦。
好了,最后不要忘了导入Ksoap-andriod 的jar包