http://sizeed.blog.163.com/blog/static/96525451201111875016395/
SOAP:简单对象访问协议,简单对象访问协议(SOAP)是一种轻量的、简单的、基于 XML 的协议。
通过第三方提供的架包ksoap2-Android-assembly-2.4-jar-with-dependencies.jar,我们可以向服务器进行请求调用自己需要的服务。下面以http://www.webxml.com.cn/提供的天气预报web服务为例。
下面是向远处服务器进行请求的详细操作类WebServiceUtil
Java代码 public class WebServiceUtil { //命名空间 private static final String NAMESPACE = "http://WebXml.com.cn/"; //WebService地址 private static final String URL = "http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl"; //需要调用的方法名 private static final String getSupportProvince = "getSupportProvince"; /** * @desc 获得洲、国内外省份和城市信息 * @return 省份列表 */ public List getAllProvince() { List allProvince = new ArrayList(); try { //1.实例化SoapObject对象 SoapObject request = new SoapObject(NAMESPACE, getSupportProvince); //2.如果方法需要参数,设置参数 //request.setProperty("参数名称", "参数值"); //3.设置Soap的请求信息,参数部分为Soap协议的版本号 SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.bodyOut = request; //4.构建传输对象 AndroidHttpTransport transport = new AndroidHttpTransport(URL); transport.debug = true; //5.访问WebService,第一个参数为命名空间 + 方法名,第二个参数为Envelope对象 transport.call(NAMESPACE + getSupportProvince, envelope); //6.解析返回的数据 SoapObject result = (SoapObject) envelope.getResponse(); int count = result.getPropertyCount(); for (int i = 0; i < count; i++) { allProvince.add(result.getProperty(i).toString()); } } catch (IOException e) { e.printStackTrace(); } catch (XmlPullParserException e) { e.printStackTrace(); } return allProvince; } }
使用还是比较简单的,在这我只以天气预报服务中提供的获取省份信息的方法getSupportProvince为例,详细的解释了基于soap协议的访问操作。
在访问远程服务器提供的服务时,有时会因为网络问题或者是服务器端问题,而导致客户端侧一直处于请求连接状态,此时我们希望可以控制请求得不到响应的超时时间TimeOut.
想要控制请求的超时时间,我们需要根据ksoap2-android-assembly-2.4-jar-with-dependencies.jar包,修改一些访问的控制类。
1.首先重写架包中的ServiceConnectionSE.Java,添加设置超时时间的方法,可以在你的工程里重写这个类
Java代码 package com.ahutzh.weather; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import org.ksoap2.transport.ServiceConnection; public class ServiceConnectionSE implements ServiceConnection { private HttpURLConnection connection; public ServiceConnectionSE(String url) throws IOException { this.connection = ((HttpURLConnection)new URL(url).openConnection()); this.connection.setUseCaches(false); this.connection.setDoOutput(true); this.connection.setDoInput(true); } public void connect() throws IOException { this.connection.connect(); } public void disconnect() { this.connection.disconnect(); } public void setRequestProperty(String string, String soapAction) { this.connection.setRequestProperty(string, soapAction); } public void setRequestMethod(String requestMethod) throws IOException { this.connection.setRequestMethod(requestMethod); } public OutputStream openOutputStream() throws IOException { return this.connection.getOutputStream(); } public InputStream openInputStream() throws IOException { return this.connection.getInputStream(); } public InputStream getErrorStream() { return this.connection.getErrorStream(); } //设置连接服务器的超时时间,毫秒级,此为自己添加的方法 public void setConnectionTimeOut(int timeout){ this.connection.setConnectTimeout(timeout); } }
再自己写一个传输对象类,类似于架包中的AndroidHttpTransport类,命名为MyAndroidHttpTransport.java
Java代码 package com.ahutzh.weather; import java.io.IOException; import org.ksoap2.transport.HttpTransportSE; import org.ksoap2.transport.ServiceConnection; public class MyAndroidHttpTransport extends HttpTransportSE { private int timeout = 30000; //默认超时时间为30s public MyAndroidHttpTransport(String url) { super(url); } public MyAndroidHttpTransport(String url, int timeout) { super(url); this.timeout = timeout; } protected ServiceConnection getServiceConnection(String url) throws IOException { ServiceConnectionSE serviceConnection = new ServiceConnectionSE(url); serviceConnection.setConnectionTimeOut(timeout); return new ServiceConnectionSE(url); } }
完成这之后,在前面的第四步构建传输对象中,就不要使用架包中的AndroidHttpTransport,而使用我们自己的写的这个类。
Java代码 //4.构建传输对象 // AndroidHttpTransport transport = new AndroidHttpTransport(URL); // transport.debug = true; int timeout = 15000; //set timeout 15s MyAndroidHttpTransport transport = new MyAndroidHttpTransport(URL, timeout); transport.debug = true;
===================================================
经过测试后,发现有问题但最后也成功了。
还是先要看ksoap2的版本吧,用的是2.5.4版本,其实这个版本的类里面已经有了timeout的设置,早期版本就不清楚了。
如ServiceConnectionSE类的构造函数:
public ServiceConnectionSE(String url, int timeout)
throws IOException
{
this.connection = ((HttpURLConnection)new URL(url).openConnection());
this.connection.setUseCaches(false);
this.connection.setDoOutput(true);
this.connection.setDoInput(true);
this.connection.setConnectTimeout(timeout);
this.connection.setReadTimeout(timeout);
}
另一个传输的类HttpTransportSE的构造函数
public HttpTransportSE(String url, int timeout)
{
super(url, timeout);
}
可见它也支持直接设置timeout,那我们直接用
HttpTransportSE ht=new HttpTransportSE(url,20000);//20秒限时
...
但测试发现,没有效果,为何呢?
经过找源代码,发现HttpTransportSE的类里面方法
protected ServiceConnection getServiceConnection() throws IOException {
return new ServiceConnectionSE(this.proxy, this.url);
}
可以看到,它新建的ServiceConnectionSE类对象,不是执行带timeout产生的构造函数,那估计ServiceConnectionSE没有设置timeout了,那就是说在HttpTransportSE构造函数指定的timeout,其实最终没有设置timeout,所以测试没有效果。
知道了这里,我们可以如下重写类。
我的方法,不需要重写ServiceConnectionSE类,而仅仅是如下
class MyAndroidHttpTransport extends HttpTransportSE
{
private int timeout =20000; //默认超时时间为20s
public MyAndroidHttpTransport(String url) {
super(url);
}
public MyAndroidHttpTransport(String url, int timeout) {
super(url);
this.timeout = timeout;
}
//尤其注意此方法
protected ServiceConnection getServiceConnection() throws IOException
{
ServiceConnectionSE serviceConnection = ServiceConnectionSE(this.url,timeout);
return serviceConnection;
}
}
注意getServiceConnection方法不同的地方,
1是没有参数url,如果有参数不能覆盖父类的同名方法;
2是原新建一个对象,而又返回一个new对象,逻辑就不通,估计没测过。
最后使用的方法是雷同的。