Android开发:SOAP与REST WebService调用实战指南

📅 2026/7/19 3:56:33 👁️ 阅读次数 📝 编程学习
Android开发:SOAP与REST WebService调用实战指南

1. Android调用WebService概述

在Android开发中,WebService是一种常见的远程服务调用方式。它基于SOAP协议或REST架构,通过HTTP/HTTPS协议实现跨平台的数据交互。对于需要与企业级系统对接的移动应用来说,WebService提供了标准化的集成方案。

WebService的核心优势在于其平台无关性。无论后端系统是用Java、.NET还是其他语言开发,只要遵循WebService标准,Android客户端都能通过简单的HTTP请求与之通信。这种特性使其在ERP系统对接、支付网关集成等企业级应用中尤为常见。

2. 准备工作与环境配置

2.1 添加网络权限

首先需要在AndroidManifest.xml中添加网络访问权限:

<uses-permission android:name="android.permission.INTERNET" />

2.2 选择WebService调用方式

Android平台主要支持两种WebService调用方式:

  1. SOAP方式

    • 需要引入ksoap2-android库
    • 适合传统企业级WebService
    • 支持WSDL规范
  2. REST方式

    • 使用HttpURLConnection或OkHttp
    • 轻量级,适合现代API设计
    • 通常返回JSON/XML格式数据

对于传统SOAP WebService,建议添加以下依赖:

implementation 'com.google.code.ksoap2-android:ksoap2-android:3.6.4'

3. SOAP WebService调用实现

3.1 构建SOAP请求

以下是一个完整的SOAP请求示例:

private static final String NAMESPACE = "http://tempuri.org/"; private static final String URL = "http://example.com/Service.asmx"; private static final String METHOD_NAME = "GetData"; private static final String SOAP_ACTION = NAMESPACE + METHOD_NAME; public void callWebService() { SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); // 添加请求参数 request.addProperty("param1", "value1"); request.addProperty("param2", 123); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = true; // 针对.NET WebService的设置 envelope.setOutputSoapObject(request); HttpTransportSE transport = new HttpTransportSE(URL); try { transport.call(SOAP_ACTION, envelope); SoapObject response = (SoapObject) envelope.getResponse(); // 处理响应数据 processResponse(response); } catch (Exception e) { e.printStackTrace(); } }

3.2 处理复杂类型响应

当WebService返回复杂对象时,需要注册映射关系:

// 在调用前添加 envelope.addMapping(NAMESPACE, "User", new User().getClass()); // 自定义类示例 public class User implements KvmSerializable { private String name; private int age; // 必须实现的方法 @Override public Object getProperty(int index) { switch(index) { case 0: return name; case 1: return age; } return null; } @Override public void setProperty(int index, Object value) { switch(index) { case 0: name = value.toString(); break; case 1: age = Integer.parseInt(value.toString()); break; } } }

4. REST WebService调用实现

4.1 使用HttpURLConnection

对于简单的REST服务,可以使用系统原生API:

public String callRestService(String urlStr) throws IOException { URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); try (InputStream is = conn.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is))) { StringBuilder response = new StringBuilder(); String line; while ((line = br.readLine()) != null) { response.append(line); } return response.toString(); } finally { conn.disconnect(); } }

4.2 使用OkHttp(推荐)

对于生产环境,建议使用OkHttp库:

implementation 'com.squareup.okhttp3:okhttp:4.9.3'

调用示例:

public void callRestApiWithOkHttp() { OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build(); Request request = new Request.Builder() .url("https://api.example.com/data") .addHeader("Authorization", "Bearer token123") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 处理失败情况 } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String jsonData = response.body().string(); // 解析JSON响应 } } }); }

5. 常见问题与解决方案

5.1 网络请求主线程限制

Android不允许在主线程执行网络操作,解决方案:

  1. 使用AsyncTask(已废弃但简单场景仍可用)
  2. 使用Thread + Handler
  3. 使用Kotlin协程
  4. 使用RxJava

协程示例(Kotlin):

lifecycleScope.launch { try { val result = withContext(Dispatchers.IO) { callWebService() } // 更新UI } catch (e: Exception) { // 处理异常 } }

5.2 超时与重试机制

建议配置合理的超时和重试策略:

OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); int tryCount = 0; while (!response.isSuccessful() && tryCount < 3) { tryCount++; response = chain.proceed(request); } return response; } }) .build();

5.3 安全配置

从Android 9(Pie)开始,默认禁止明文HTTP请求,解决方法:

  1. 使用HTTPS
  2. 或配置网络安全策略(res/xml/network_security_config.xml):
<network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">example.com</domain> </domain-config> </network-security-config>

然后在Manifest中引用:

<application android:networkSecurityConfig="@xml/network_security_config" ... >

6. 性能优化建议

6.1 请求缓存

对频繁请求且数据变化不频繁的接口实现缓存:

Cache cache = new Cache(new File(context.getCacheDir(), "http-cache"), 10 * 1024 * 1024); OkHttpClient client = new OkHttpClient.Builder() .cache(cache) .addInterceptor(new CacheInterceptor()) .build(); // 自定义缓存拦截器 class CacheInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (!isNetworkAvailable()) { request = request.newBuilder() .header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24) .build(); } return chain.proceed(request); } }

6.2 数据压缩

启用Gzip压缩减少传输数据量:

OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new GzipRequestInterceptor()) .build(); class GzipRequestInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); Request compressedRequest = originalRequest.newBuilder() .header("Accept-Encoding", "gzip") .method(originalRequest.method(), gzip(originalRequest.body())) .build(); return chain.proceed(compressedRequest); } private RequestBody gzip(final RequestBody body) { return new RequestBody() { @Override public MediaType contentType() { return body.contentType(); } @Override public void writeTo(BufferedSink sink) throws IOException { BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); body.writeTo(gzipSink); gzipSink.close(); } }; } }

6.3 连接池优化

复用HTTP连接提升性能:

ConnectionPool connectionPool = new ConnectionPool(5, 10, TimeUnit.MINUTES); OkHttpClient client = new OkHttpClient.Builder() .connectionPool(connectionPool) .build();

7. 高级应用场景

7.1 文件上传

使用Multipart实现文件上传:

public void uploadFile(File file, String mimeType) { RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", file.getName(), RequestBody.create(file, MediaType.parse(mimeType))) .addFormDataPart("description", "file upload") .build(); Request request = new Request.Builder() .url("https://api.example.com/upload") .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { // 处理响应 }); }

7.2 WebService安全认证

对于需要认证的WebService,添加安全头:

// Basic认证 String credential = Credentials.basic("username", "password"); Request request = new Request.Builder() .url(url) .header("Authorization", credential) .build(); // WS-Security认证(SOAP) SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); Element[] header = new Element[1]; header[0] = new Element().createElement(NAMESPACE, "Security"); request.addHeader(header);

7.3 使用Retrofit简化REST调用

Retrofit是类型安全的HTTP客户端:

implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

定义API接口:

public interface ApiService { @GET("users/{id}") Call<User> getUser(@Path("id") int userId); @POST("users") Call<Void> createUser(@Body User user); }

创建服务实例:

Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build(); ApiService service = retrofit.create(ApiService.class);

8. 调试与测试技巧

8.1 使用Stetho调试网络请求

Facebook的Stetho工具可以方便地调试网络请求:

debugImplementation 'com.facebook.stetho:stetho:1.6.0' debugImplementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'

初始化:

Stetho.initializeWithDefaults(this); OkHttpClient client = new OkHttpClient.Builder() .addNetworkInterceptor(new StethoInterceptor()) .build();

8.2 Mock WebService响应

使用MockWebServer进行单元测试:

testImplementation 'com.squareup.okhttp3:mockwebserver:4.9.3'

测试示例:

@Test public void testWebService() throws Exception { MockWebServer server = new MockWebServer(); server.start(); server.enqueue(new MockResponse() .setBody("{\"name\":\"test\",\"age\":30}") .setHeader("Content-Type", "application/json")); ApiService service = new Retrofit.Builder() .baseUrl(server.url("/")) .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiService.class); Call<User> call = service.getUser(1); User user = call.execute().body(); assertEquals("test", user.getName()); assertEquals(30, user.getAge()); server.shutdown(); }

8.3 使用Charles Proxy抓包

Charles是强大的HTTP抓包工具,配置方法:

  1. 手机和电脑连接同一WiFi
  2. 手机设置手动代理,指向电脑IP,端口8888
  3. 在Charles中允许连接
  4. 安装Charles证书到手机(用于HTTPS解密)

注意:生产环境务必关闭代理,测试环境使用后也应清除证书