本来以为在java平台上用axis2生成了客户端代理类然后移植到Android平台上就好了。没想到在移植过程中出现了很多问题。说明JVM和android的DVM差距还是很大的。
JVM执行的是class文件,而DVM执行的是dex文件。
在eclipse里面开发Android程序的时候在编译时会把jar包里面的class一个个编译成DVM可执行的dex文件。当然,有个前提是jar包是放在source folder里面的。这样eclipse才会在编译程序的时候将jar包编译到apk文件中去。要不然虽然本地eclipse不会报错,但是在模拟器中会报错NoClassDefFound。
而且有的jar包是不能被dexdump.exe正确转换成dex文件的。这样就导致这个jar包不能用,后果是整个程序都不能正确运行。
我在将axis2移植到Android平台上去的时候有一些jar包转换不了。然后网上找了很多资料,都没人解决这个问题。希望如果有人解决了能共享一下下。
后来实在不行了,看网上说在Android平台都用ksoap2来调用Web Service。自己觉得解决不了axis2的问题。于是只能改变方向。学习了一下ksoap2。在ksoap2调用WCF服务的时候也出现了很多问题。好在后来慢慢都解决了。现在将我遇到的问题和解决的方案都写下来,供其他也碰到这些问题的人参考。
下面列举一下我碰到的问题和解决方案
1.调用是参数的说明
Namespace 是你设置的服务命名空间,一般没有设置就是http://tempuri.org/
URL是你服务暴露的地址,通过这个地址可以获取wsdl。在android里面127.0.0.1代表的是模拟器的地址,而10.0.0.2代表的才是电脑的127.0.0.1。所以如果是自己本机做WCF服务器的话,程序里面应该这么设置。
SOAP_ACTION是你的wsdl里面相对应的方法的地址。
MethodName就是SOAP_ACTION最后面的那个指明ACTION的方法名。
2.参数传递 复杂对象
服务里面不可避免的是会传递参数,但是在可能在wcf服务端可能解析不了你传的参数。通过tcptrace截取soap后发现是参数的namespace不对应的原因。下面是一个例子
服务端代码:
User类:
android客户端代码如下:
android端也有一个User类,这个类是继承的BaseObject,BaseObject实现KvmSerializable接口
先BaseObject:
然后是User类
因为要序列化啊什么什么的,解释起来比较烦。这边也不解释了。大家有兴趣可以去查一下。只说明一下是通过info.namespace+info.name来反序列化的。
3.如果有证书加密,会一直说timeout。
解决方法是在android客户端调用下面这个方法。这个方法要在httptransport.call()之前调用
类是这么写的:
这个信任一切证书。应为自制的证书是不被信任的,所以shakehand的时候一直timeout。
4.wcf设置的自定义帐号密码认证(userNameAuthentication )
加入这个之后要在soap发送前在head里面加入用户信息。
加入的方法是:
这个需要重写httptransport的getServiceConnection()方法。
因为在调用httptransport.call()的时候Connection才被初始化,所以在程序外getServiceConnection().setRequestProperty()会报错说nullpoint。
希望对大家有所帮助。
贴一下解析代码: