概述
在后端使用webservice和移动端交互的时候,移动端(安卓)需要导入一个jar包:ksoap2-android-assembly-3.3.0-jar-with-dependencies或者使用gradle引入也可,
然后自己需要封装webservice去和后端交互,比如这样的:
String namespace = "";
String transUrl = "";
String method = "";
//注意版本使用,这个需要跟后台询问或者从wsdl文档或者服务说明中查看
int envolopeVersion = SoapEnvelope.VER12;
//soapAction是namspace+method拼接
String soapAction = namspace+method;
SoapObject request = new SoapObject(namespace, method);
//参数一定注意要有序,尽管是addProperty(),不要当作HttpUrl可以使用LinkedHashMap封装
request.addProperty("", "");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(envolopeVersion);
envelope.setOutputSoapObject(request);
//envelope.dotNet = true;
HttpTransportSE se = new HttpTransportSE(transUrl);
try {
//se.call(soapAction, envelope); //ver11,第一个参数不能为空
se.call(null, envelope);//envolopeVersion为ver12第一个参数可以为空,必须接口支持ver12才行
SoapObject response = (SoapObject) envelope.bodyIn;
//response的处理需要根据返回的具体情况,基本都要进行下面一步
SoapObject o = (SoapObject) response.getProperty(0);
//当前方法返回的结果为一个数组
Log.e("Log", "->" + o.getPropertyCount());
for (int i = 0; i < o.getPropertyCount(); i++) {
Log.e("Log", "->" + o.getPropertyAsString(i));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
,进行本地化封装后需要自己每次都专门去解析这些响应后的数据,但是接口一旦多了就比较麻烦了
这里有个大牛总结了一个这样的框架:com.github.joaocruz04:jsoap:1.0.2,目前最新版本是1.0.2,
有兴趣的可以去查看下他的源码,但是在源码中我发现了其中一个问题就是在不能解析单个对象,
类似于这样的:
地址为:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getSupportCity
拿到的响应结果为:
HTTP/1.1 200 OK Content-Type: application/soap+xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <soap12:Body> <getSupportCityResponse xmlns="http://WebXml.com.cn/"> <getSupportCityResult> <string>string</string> <string>string</string> </getSupportCityResult> </getSupportCityResponse> </soap12:Body> </soap12:Envelope>
,经过调试和查看原因是在SoapDeserializer中的setObjectValue没有对这样的特殊的结构进行解析,源码是这样的:
private void setObjectValue(Field f, SoapObject object, String name, boolean isAttribute) { if (f.getType().equals(String.class)) { setStringValue(object, name, f, isAttribute); } else if (f.getType().equals(Integer.class) || f.getType().equals(int.class)) { setIntValue(object, name, f, isAttribute); } else if (f.getType().equals(Boolean.class) || f.getType().equals(boolean.class)) { setBooleanValue(object, name, f, isAttribute); } else if (f.getType().equals(Double.class) || f.getType().equals(double.class)) { setDoubleValue(object, name, f, isAttribute); } else if (f.getType().equals(Float.class) || f.getType().equals(float.class)) { setFloatValue(object, name, f, isAttribute); } else if (SOAPDeserializable.class.isAssignableFrom(f.getType())) { setObjectValue(object, name, f, isAttribute); } else if (f.getType().isArray()) { if (f.getType().getComponentType().equals(String.class)) { setStringArrayValue(object, f); } else if (f.getType().getComponentType().equals(Integer.class) || f.getType().getComponentType().equals(int.class)) { setIntArrayValue(object, f); } else if (SOAPDeserializable.class.isAssignableFrom(f.getType().getComponentType())){ setObjectArrayValue(object, f); } else if (f.getType().getComponentType().equals(Float.class) || f.getType().getComponentType().equals(float.class)) { setFloatArrayValue(object, f); } else if (f.getType().getComponentType().equals(Double.class) || f.getType().getComponentType().equals(double.class)) { setDoubleArrayValue(object, f); } else if (f.getType().getComponentType().equals(Boolean.class) || f.getType().getComponentType().equals(boolean.class)) { setBooleanArrayValue(object, f); } } }
还需要在加上对object的处理,这里是修改的方法:
/** * 给属性赋值 * * @param originalObjec * @param f * @param object * @param name * @param isAttribute */ private static void setObjectValue(Object originalObjec, Field f, SoapObject object, String name, boolean isAttribute) { if (f.getType().equals(String.class)) { setStringValue(originalObjec, object, name, f, isAttribute); } else if (f.getType().equals(Integer.class) || f.getType().equals(int.class)) { setIntValue(originalObjec, object, name, f, isAttribute); } else if (f.getType().equals(Boolean.class) || f.getType().equals(boolean.class)) { setBooleanValue(originalObjec, object, name, f, isAttribute); } else if (f.getType().equals(Double.class) || f.getType().equals(double.class)) { setDoubleValue(originalObjec, object, name, f, isAttribute); } else if (f.getType().equals(Float.class) || f.getType().equals(float.class)) { setFloatValue(originalObjec, object, name, f, isAttribute); } else if (originalObjec.getClass().isAssignableFrom(f.getType())) { setObjectValue(originalObjec, object, name, f, isAttribute); } else if (f.getType().isArray()) { if (f.getType().getComponentType().equals(String.class)) { setStringArrayValue(originalObjec, object, f); } else if (f.getType().getComponentType().equals(Integer.class) || f.getType().getComponentType().equals(int.class)) { setIntArrayValue(originalObjec, object, f); } else if (f.getType().getComponentType().equals(Float.class) || f.getType().getComponentType().equals(float.class)) { setFloatArrayValue(originalObjec, object, f); } else if (f.getType().getComponentType().equals(Double.class) || f.getType().getComponentType().equals(double.class)) { setDoubleArrayValue(originalObjec, object, f); } else if (f.getType().getComponentType().equals(Boolean.class) || f.getType().getComponentType().equals(boolean.class)) { setBooleanArrayValue(originalObjec, object, f); } else { setObjectArrayValue(originalObjec, object, f); } } else {//这里是新添加的地方,有的类将类作为属性 setObjectValue(originalObjec, object, name, f, isAttribute); } }
还有在SOAPManager类中的get方法中有一行是这样的:
Object reslt = envelope.getResponse();
这里简答说下:
envelope两种方式获取服务器返回的信息
1.envelope.getResponse();
2.envelope.bodyIn;
这两种返回的东西是有些区别的
两者的区别:Webservice开发的时候一般情况下大家接受webservice服务器返回值的时候都是使用
SoapObject soapObject = (SoapObject) envelope.getResponse();这个来接受返回来的值,但这种方法往往会产生java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive这样的错误。
在服务器端返回值是String类型的数值的时候使用SoapObject soapObject = (SoapObject)
envelope.getResponse()会产生java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive这样的错误。
使用SoapObject result = (SoapObject)envelope.bodyIn和 Object object = envelope.getResponse();就可以解决这种错误。
如果服务器返回值的类型是byte[] 的时候,使用Object object = envelope.getResponse();和SoapObject result = (SoapObject)envelope.bodyIn;都不会发生错误现象,但是在使用Object object = envelope.getResponse();取回来的值在使用base64进行解码和编码的时候会报出错误。
如果使用SoapObject result = (SoapObject)envelope.bodyIn;就可以完整的将byte[]进行解码和编码,byte[] ops = Base64.decode(result.getProperty(0).toString());
SoapObject result=(SoapObject) envelope.bodyIn;
String str=result.getProperty(0).toString();
或者是
Object result= (Object) reqVo.envelope.getResponse();
String str=result.toString();
所以建议将这个
Object reslt = envelope.getResponse();
改为
Object reslt = envelope.bodyIn;
如有错误不当之处,望请指正。
转载于:https://my.oschina.net/u/3726375/blog/1793190
最后
以上就是执着红牛为你收集整理的移动端(安卓)使用webservice访问后端的全部内容,希望文章能够帮你解决移动端(安卓)使用webservice访问后端所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复