Android 使用KSOAP2调用WebService

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 使用KSOAP2调用WebService相关的知识,希望对你有一定的参考价值。

soapObject = (SoapObject) envelope.getResponse(); soapObject = (SoapObject) envelope.bodyIn; 具体指啥意思? 区别、用法? 始终连接报错03-18 13:47:21.659: WARN/System.err(479): SoapFault - faultcode: 'soap:Client' faultstring: '�0�3�0�8�0�3�0�2�0�0�0�3�0�2�0�5¨�0�3�0�8�0�9è�0�3�0�5è�0�4�0�6�0�2�0�8�0�0 HTTP �0�2¤�0�7 SOAPAction �0�4�0�6�0�4�0�2�0�0�0�4: �0�0�0�0�0�2' faultactor: 'null' detail: org.kxml2.kdom.Node@437b25a0
03-18 13:47:21.670: WARN/System.err(479): at org.ksoap2.serialization.SoapSerializationEnvelope.parseBody(SoapSerializationEnvelope.java:112)
03-18 13:47:21.670: WARN/System.err(479): at org.ksoap2.SoapEnvelope.parse(SoapEnvelope.java:137)

android 利用ksoap2方式连接webservice(2010-04-16 16:36:25)转载标签:androidksoap2webserviceit 分类:Android
利用J2SE的ksoap2标准,我也来做一个山寨版本的android连接webservice。因为soap封装的关系,android application在接收到数据后不能够正确的按照J2SE的标准来获取。

在运用之前,我们先要引导两个jar进入工程的buildpath

这两个jar包都可以在网上查到下载,引导完后再做一项准备工作。弄清楚已发布的webservice的地址,以及封装的方式。比如:

webservice接口: http://192.168.0.2:8080/axis2/services/Manager?wsdl (顺便说明一下,在android当中,不能写localhost,必须写清楚PC机当前的网络IP)
webservice封装: http://ws.apache.org/axis2

都了解了过后,说明已经做好准备了。
下面就介绍一下android如何获取webservice封装数据。。

引入ksoap2中以封装好的类
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.AndroidHttpTransport;

在类中定义webservice的接口地址以及解析方式并且定义要调用的webservice中的函数
private static final String URL = " http://192.168.0.2:8080/axis2/services/Manager?wsdl";
private static final String NAMESPACE = " http://ws.apache.org/axis2";
private static final String METHOD_NAME = "GetMyFriends";

这个信息我们可以在webservice中查到
<xs:element name="GetMyFriends">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="userId" type="xs:int"/>
<xs:element minOccurs="0" name="password" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

接下来开始做对webservice请求数据的工作,请求webservice函数以及封装要用的两个参数(userId和password)
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("userId", "123456");
request.addProperty("password", "test");
之后我们给定义发送数据的信封的封装格式
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11 );
发出请求
envelope.setOutputSoapObject(request);
AndroidHttpTransport aht = new AndroidHttpTransport(URL);
aht.call(null, envelope);

接着就可以定义一个SoapObject类型的实例去获取我们返回来的数据
SoapObject so = (SoapObject) envelope.bodyIn;
这里如果是返回来的数据只有一行并且只有一个值,比如验证函数,返回boolean类型的话,操作比较简单,String getReturn= so.getProperty("return"); 这个getReturn就是你要获取的值。
但是如果返回来是多行的值的话,这个方法就不行了,我们必须对返回来的信息做一些解析。我曾试过用J2SE的标准方式来获取,但是会报错,最主要的可能是他的方式在android当中不能使用。所以在这里我用了正则表达式这种方式来进行数据的解析,我们先来看一下他返回的数据的结构是什么情况。
GetMyFriendsResponsereturn=FriendsMessage <br>permitList=anyTypenickName=我爱罗; singnature=null; userId=2; ; permitList=anyTypenickName=jack; singnature=null; userId=1004; ; permitList=anyTypenickName=admin; singnature=leo_admin; userId=1001; ;;
简单看他很想Json结构,但是确不是。。。
就目前的解决方式,我只是通过规律来进行了正则表达式的解析:如解析上面的内容。

//首先取得permitList(好友)的个数
String testPattern = "permitList";
int resultlength = result.length();
cresult = cresult.replace(testPattern, "");
int lastlength = (resultlength - cresult.length()) / testPattern.length();

//取得每个permitList中的值。
String LoginReturn="", pattern="nickName=.*?;\\s*singnature=.*?;\\s*userId=.*?;";
//动态生成String 数组,存储每个好友的信息
String[] GetFinalReturn = new String[lastlength];
for (int i=0;i<lastlength;i++)
LoginReturn = result.replaceFirst("^.*("+pattern+").*$", "$1");
GetFinalReturn[i] = LoginReturn;
result = result.replace(LoginReturn,"");

这个数组里面存储的格式就是nickName=admin; singnature=leo_admin; userId=1001;
这样以来,我们可以根据"="和";"两个符号之间做split操作就可以得到数据。

好了,到此连接webservice和解析返回来的数据的工作就做完了,虽然这个方式看起来很复杂,但是目前来说,用ksoap2方式来连接webservice暂时还没有找到更有效的解决方式。。
参考技术A 下是调用的几个主要的方法:
1.创建HttpTransportSE传输对象:HttpTransportSE ht = new HttpTransportSE(SERVICE_URL); SERVICE_URL是webservice提供服务的url
2.使用SOAP1.1协议创建Envelop对象:SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 设置SOAP协议的版本号,根据服务端WebService的版本号设置。
3.实例化SoapObject对象:SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName); 第一个参数表示WebService的命名空间,可以从WSDL文档中找到WebService的命名空间。第二个参数表示要调用的WebService方法名。
4.设置调用方法的参数值,如果没有参数,可以省略:例如soapObject.addProperty("theCityCode", cityName);
5.记得设置bodyout属性 envelope.bodyOut = soapObject;
6.调用webservice:ht.call(SERVICE_NAMESPACE+methodName, envelope);
7.获取服务器响应返回的SOAP消息:
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName+"Result");
参考技术B 前一个是获得调用webservice返回的SOAP格式的数据,格式一般如下:
POST
/WebServices/ValidateCodeWebService.asmx
HTTP/1.1
Host:
www.webxml.com.cn
Content-Type:
text/xml;
charset=utf-8
Content-Length:
length
SOAPAction:
"http://WebXml.com.cn/enValidateImage"
<?xml
version="1.0"
encoding="utf-8"?>
<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<enValidateImage
xmlns="http://WebXml.com.cn/">
<byString>string</byString>
</enValidateImage>
</soap:Body>
</soap:Envelope>
后一个应该是获取上述内容中<soap:Body>标签中的内容。。。。
对于你所说的错误,我觉得可能是调用webservice方法时写的代码有问题,你仔细检查一下方法传递的参数以及参数的格式是否正确。。。。

在Android中调用KSOAP2库访问webservice服务出现的服务端返回AnyType{}

  最近在做毕业设计的时候,涉及到了安卓端访问web service服务端数据库,并返回一个值,当我把web service测试通过后,想写一个简单的安卓测试程序,来实现服务端数据库访问,通过web service中的一个serch()方法,然后发现,每次的返回值都是一个AnyType{},Logcat如图所示:

 

 

 

 

 

 

 

 

 

  网上搜集了很多资料,产生的原因其实很简答,是因为服务端返回值为null,Logcat中显示的就职anyType{},找到了原因,解决起来也就好说了,其中包括这些方法:

  {解决方法引用自博客园用户日行一米,这里表示感谢}

  1、只需要在 WebService的类属性中加入SoapRpcServiceAttribute属性就可以了。
      [SoapRpcService(RoutingStyle=SoapServiceRoutingStyle.SoapAction)]

     2、参数名必须跟webservice方法中的参数名一致,因为ws将参数名自动改为了arg0、arg1,所有调用时参数也需要修改。

     3、NAMESPACE  后面没有加“/”

  特此说明:

  方法一我不知道去哪儿加,看博主在解决问题时候,说方法一加了之后,直接报了异常,我也就没管。

  方法二则是我解决问题的关键,看我的Logcat中,传入参数为 username = 10010,所以传过去之后变量是username(目前我是这样认为),而webservice会将参数名自动改为arg0、arg1......所以参数不同,导致了传回的结果变成了null,显示return anyType{}。

        //调用方法时需要传入一个参数
        //为了与web service保持一致,需要设置为arg0,因为web service会自动将其转化为arg0 arg1
        rpc.addProperty("arg0",username);

 

  还有一个原因就是

            //设置是否调用的是dotNet开发的WebService,服务器是.net的需要设置为true,java不用
            envelope.dotNet = false; 

  我的服务端用的Java写的,所以这个属性应该设置为false。

至此,我的问题已经解决了!!!

  2017.4.23

  今天又遇到了同样的问题,但是这次就是从以前的经验中,来寻找问题了。我在返回一个存放有Map的List时候,出现了返回值为NULL的情况,Logcat里边显示的就是AnyType{},这次肯定是其他原因。

  仔细观察了一下代码,发现我在定义Map的时候是这样定义的:

  HashMap<String, String> map = new HashMap<String,String>();

  同理,拿我的List定义就是这样:

  ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();

  相比之前的定义,不一样的地方好像是Map<>中的两个参数。可能因为返回的数据不一定都是String类型的原因吧,但真正为什么,我也不清楚。只是更改了一下里边的参数这个返回值问题才解决,代码如下:

1     ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String,Object>>();
2     HashMap<String, Object> map = new HashMap<String,Object>();

  有问题再来补充吧!!!

以上是关于Android 使用KSOAP2调用WebService的主要内容,如果未能解决你的问题,请参考以下文章

通过ksoap2-android来调用Web Service操作的实例

android 调用.NET WebServices

Ksoap2 Android - 如何为复杂对象的子属性指定命名空间?

使用具有复杂对象的 KSoap2 调用 WCF 服务。 WCF 接收空值

在Android中调用KSOAP2库访问webservice服务出现的服务端返回AnyType{}

我如何在异步任务中进行ksoap2调用?