Android基于SOAP协议向WebService交互数据,修改请求超时时间

来源:互联网 发布:mac sacd 编辑:程序博客网 时间:2024/05/31 06:21
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对象,逻辑就不通,估计没测过。

最后使用的方法是雷同的。

0 0