Retrofit是当前使用最为广泛的Android网络请求框架,它可以构建不同的网络请求格式进行网络请求,使用Retrofit我们可以根据SOAP协议构建网络请求,此次记录一次完整的构建过程。

在前面的文章在Android中使用SOAP通信写了SOAP协议,其本质上是XML+HTTP,使用HTTP协议进行XML格式数据的通信。如果一个客户端向不同的后台服务器进行数据通信时,多网络框架的使用是非常不便的。

Retrofit是当前使用最为广泛的Android网络请求框架,它可以构建不同的网络请求格式进行网络请求,使用Retrofit我们可以根据SOAP协议构建网络请求,此次记录一次完整的构建过程。

一、Retrofit框架引入

主要是Retrofit和OkHttp框架。

1
2
3
4
5
6
7
8
compile 'com.squareup.okhttp3:okhttp:3.6.0'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile('com.squareup.retrofit2:converter-simplexml:2.1.0') { //simplexml构建xml请求
exclude group: 'xpp3', module: 'xpp3'
exclude group: 'stax', module: 'stax-api'
exclude group: 'stax', module: 'stax'
}

二、请求构建

  1. 获取SOAP请求结构

    首先使用抓包工具对网络请求进行抓包(抓包的教程可以百度),获取数据包,然后使用postman进行数据调试。下面是我的调试成功数据:

    请求数据

    返回数据

  2. 使用simplexml构建请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    /**
    * 1.RequestEnvelope构建
    */
    @Root(name = "soapenv:Envelope")
    @NamespaceList({
    @Namespace(reference = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi"),
    @Namespace(reference = "http://www.w3.org/2001/XMLSchema", prefix = "xsd"),
    @Namespace(reference = "http://schemas.xmlsoap.org/soap/envelope/", prefix = "soapenv")
    })
    public class RequestEnvelope {
    @Element(name = "soapenv:Body", required = false)
    public RequestBody requestBody;
    }
    @Root(name = "soapenv:Body", strict = false)
    public class RequestBody {
    @Element(name = "GetCommand", required = false)
    public RequestModel GetCommand;
    }
    public class RequestModel {
    @Attribute(name = "xmlns")
    public String Attribute;
    @Element(name = "E_SN", required = false)
    public String E_SN;
    }
    /*
    *2.ResponseEnvelope构建
    */
    @Root(name = "soapnev:Envelope")
    @NamespaceList({
    @Namespace(reference = "http://schemas.xmlsoap.org/soap/envelope/", prefix = "soapenv"),
    @Namespace(reference = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi"),
    @Namespace(reference = "http://www.w3.org/2001/XMLSchema", prefix = "xsd")
    })
    public class ResponseEnvelope {
    @Element(name = "Body")
    public ResponseBody responseBody;
    }
    @Root(name = "Body")
    public class ResponseBody {
    @Element(name = "GetCommandResponse",required = false)
    public GetCommandResponse getCommandResponse;
    }
    @Root(name = "GetCommandResponse")
    @Attribute(name = "xmlns",empty = "http://mobiletone.cn/")
    public class GetCommandResponse {
    @Element(name = "GetCommandResult",required = false)
    public String GetCommandResult;
    }
    /**
    * 3.API接口编写
    */
    @Headers({
    "Content-Type:text/xml;charset=utf-8",
    "SOAPAction:http://*********"
    })
    @POST("WEBSERVICE/Services.asmx")
    Observable<ResponseEnvelope> getCommand(@Body RequestEnvelope requestEnvelope);

    PS : 在构建RequestEnvelope时,不同的SOAP协议版本(该次请求是VER11)@NamespaceList头部是有差异的,需要根据调试信息调整。

  3. 发送请求,并解析返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    /**
    * 1.Retrofit初始化
    */
    public class RetrofitGenerator {
    private static OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
    private static final String BASE_URL = "*********";
    private static Strategy strategy = new AnnotationStrategy();
    private static Serializer serializer = new Persister(strategy);
    private static ServerRequest serviceRequest;
    private static Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
    .addConverterFactory(SimpleXmlConverterFactory.create(serializer))
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .baseUrl(BASE_URL);
    private static <S> S createRetrofit(Class<S> cls) {
    okHttpBuilder.interceptors().add(new Interceptor() {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
    Request original = chain.request();
    Request.Builder requestBuilder = original.newBuilder()
    .header("Content-Type", "text/xml;charset=UTF-8")
    .method(original.method(), original.body());
    Request request = requestBuilder.build();
    return chain.proceed(request);
    }
    });
    OkHttpClient client = okHttpBuilder.connectTimeout(2, TimeUnit.MINUTES)
    .writeTimeout(2, TimeUnit.MINUTES)
    .readTimeout(2, TimeUnit.MINUTES)
    .build();
    Retrofit retrofit = retrofitBuilder.client(client).build();
    return retrofit.create(cls);
    }
    public static ServerRequest getServiceStore() {
    if (serviceRequest == null) {
    serviceRequest = createRetrofit(ServerRequest.class);
    }
    return serviceRequest;
    }
    }
    /**
    * 2.参数填写
    */
    public class RequestConstruct {
    public static Observable<ResponseEnvelope> getCommand() {
    RequestEnvelope requestEnvelop = new RequestEnvelope();
    RequestBody requestBody = new RequestBody();
    RequestModel requestModel = new RequestModel();
    requestModel.Attribute = NAME_SPACE;
    requestModel.E_SN = IConfig.E_SN_VALUE;
    requestBody.GetCommand = requestModel;
    requestEnvelop.requestBody = requestBody;
    return RetrofitGenerator.getServiceStore().getCommand(requestEnvelop);
    }
    }
    /**
    * 3.订阅获取返回值
    */
    public void subscribe(){
    RequestConstruct.getCommand().subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<ResponseEnvelope>() {
    @Override
    public void call(ResponseEnvelope responseEnvelope) {
    String result =responseEnvelope.responseBody.getCommandResponse.GetCommandResult;
    }
    });
    }