Android 调用 WebService
在 Android 开发中,调用 WebService 是一种常见的网络操作,用于与服务器端的 Web 服务进行交互。WebService 通常基于 SOAP(Simple Object Access Protocol)或 REST 协议,Android 开发中主要使用 HTTP 请求(如通过 HttpURLConnection
、OkHttp 或 Retrofit)来调用 WebService。由于 SOAP WebService 在 Android 中需要处理 XML 数据,而 REST WebService 通常使用 JSON,两种方式的实现有所不同。本指南将重点讲解 Android 调用 WebService 的方法,涵盖 SOAP 和 REST,结合 HttpURLConnection
和第三方库(如 OkHttp、Retrofit),提供代码示例、注意事项和实践建议。
一、WebService 概述
- 定义:WebService 是一种跨平台、跨语言的应用程序通信方式,通过标准协议(如 SOAP 或 REST)提供服务。
- 类型:
- SOAP WebService:基于 XML,使用 WSDL(Web Service Description Language)定义接口,复杂但规范。
- REST WebService:基于 HTTP,使用 JSON 或 XML,简洁且流行。
- Android 调用方式:
- SOAP:通过
HttpURLConnection
或第三方库(如 kSOAP2)发送 XML 请求,解析 XML 响应。 - REST:通过
HttpURLConnection
, OkHttp 或 Retrofit 发送 HTTP 请求,解析 JSON/XML 响应。 - 适用场景:
- SOAP:企业级应用、银行系统、遗留系统。
- REST:现代 API、移动端开发。
二、准备工作
- 权限声明:
在AndroidManifest.xml
中添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- 依赖添加:
- kSOAP2(SOAP 专用库):
gradle implementation 'com.github.ksoap2-android:ksoap2-android:3.6.4'
- OkHttp(REST 或通用):
gradle implementation 'com.squareup.okhttp3:okhttp:4.12.0'
- Retrofit(REST 推荐):
gradle implementation 'com.squareup.retrofit2:retrofit:2.11.0' implementation 'com.squareup.retrofit2:converter-gson:2.11.0' // JSON 解析 implementation 'com.squareup.retrofit2:converter-simplexml:2.11.0' // XML 解析(SOAP)
- WebService 信息:
- SOAP:需要 WSDL URL、命名空间(namespace)、方法名、SOAP Action。
- REST:需要 API 端点 URL、HTTP 方法(GET/POST 等)、请求/响应格式(JSON/XML)。
- 示例 SOAP WSDL:
http://example.com/service?wsdl
- 示例 REST API:
https://api.example.com/users
- 异步处理:
- Android 不允许在主线程执行网络操作,需使用子线程、AsyncTask(已废弃)或 Kotlin 协程。
三、调用 SOAP WebService
SOAP WebService 使用 XML 格式通信,Android 通常使用 kSOAP2 库简化调用,结合 HttpURLConnection
处理 XML 数据。
1. 使用 kSOAP2 调用 SOAP WebService
kSOAP2 是 Android 上调用 SOAP WebService 的常用库,支持构造 SOAP 请求和解析响应。
- 示例 SOAP 请求:
假设调用一个天气服务,WSDL 定义如下: - 命名空间:
http://WebXml.com.cn/
- 方法名:
getWeatherbyCityName
- SOAP Action:
http://WebXml.com.cn/getWeatherbyCityName
- WSDL URL:
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
- 代码示例:
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
public class SoapClient {
private static final String NAMESPACE = "http://WebXml.com.cn/";
private static final String METHOD_NAME = "getWeatherbyCityName";
private static final String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";
private static final String URL = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx";
public static String callWeatherService(String cityName) {
try {
// 1. 创建 SOAP 请求
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("theCityName", cityName);
// 2. 创建 SOAP 信封
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true; // 如果是 .NET 服务,设置为 true
envelope.setOutputSoapObject(request);
// 3. 发送请求
HttpTransportSE transport = new HttpTransportSE(URL);
transport.call(SOAP_ACTION, envelope);
// 4. 获取响应
SoapObject response = (SoapObject) envelope.getResponse();
StringBuilder result = new StringBuilder();
for (int i = 0; i < response.getPropertyCount(); i++) {
result.append(response.getProperty(i).toString()).append("\n");
}
return result.toString();
} catch (Exception e) {
e.printStackTrace();
return "Exception: " + e.getMessage();
}
}
}
- 使用示例(异步调用):
new Thread(() -> {
String result = SoapClient.callWeatherService("上海");
runOnUiThread(() -> {
Log.d("SOAP", result);
});
}).start();
- 说明:
NAMESPACE
和SOAP_ACTION
从 WSDL 获取。envelope.dotNet = true
用于 .NET 服务。- 响应是 XML 格式,需进一步解析(如使用
XmlPullParser
)。
2. 使用 HttpURLConnection 调用 SOAP
如果不使用 kSOAP2,可以手动构造 SOAP XML 请求。
- 代码示例:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class SoapClientManual {
public static String callWeatherService(String cityName) {
HttpURLConnection conn = null;
try {
// 1. 创建 SOAP 请求 XML
String soapRequest = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soap:Body>" +
"<getWeatherbyCityName xmlns=\"http://WebXml.com.cn/\">" +
"<theCityName>" + cityName + "</theCityName>" +
"</getWeatherbyCityName>" +
"</soap:Body>" +
"</soap:Envelope>";
// 2. 配置连接
URL url = new URL("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx");
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
conn.setRequestProperty("SOAPAction", "http://WebXml.com.cn/getWeatherbyCityName");
// 3. 发送请求
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(soapRequest);
dos.flush();
dos.close();
// 4. 获取响应
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
return response.toString();
} else {
return "Error: HTTP " + responseCode;
}
} catch (Exception e) {
e.printStackTrace();
return "Exception: " + e.getMessage();
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
}
- 使用示例:
new Thread(() -> {
String result = SoapClientManual.callWeatherService("上海");
runOnUiThread(() -> {
Log.d("SOAP", result);
});
}).start();
- 说明:
- 手动构造 SOAP XML,复杂且易出错。
- 响应是 XML 格式,需用
XmlPullParser
或 SAX 解析(参考上一部分“Android XML 数据解析”)。 - 推荐使用 kSOAP2 简化 SOAP 调用。
四、调用 REST WebService
REST WebService 通常使用 JSON 或 XML 格式,Android 推荐使用 Retrofit 或 OkHttp 调用。
1. 使用 Retrofit 调用 REST WebService
Retrofit 简化 REST API 调用,适合 JSON 或 XML 响应。
- 示例 REST API:
- URL:
https://api.example.com/users
- 响应(JSON):
[ {"id": 1, "name": "Alice", "age": 25}, {"id": 2, "name": "Bob", "age": 30} ]
- 定义模型类:
public class User {
private int id;
private String name;
private int age;
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', age=" + age + "}";
}
}
- 定义接口:
import retrofit2.Call;
import retrofit2.http.GET;
import java.util.List;
public interface RestService {
@GET("users")
Call<List<User>> getUsers();
}
- 调用代码:
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import java.util.List;
public class RestClient {
public static String callRestService(String baseUrl) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
RestService service = retrofit.create(RestService.class);
try {
Call<List<User>> call = service.getUsers();
Response<List<User>> response = call.execute();
if (response.isSuccessful() && response.body() != null) {
StringBuilder result = new StringBuilder();
for (User user : response.body()) {
result.append(user.toString()).append("\n");
}
return result.toString();
} else {
return "Error: HTTP " + response.code();
}
} catch (Exception e) {
e.printStackTrace();
return "Exception: " + e.getMessage();
}
}
}
- 使用示例(Kotlin 协程):
interface RestService {
@GET("users")
suspend fun getUsers(): List<User>
}
suspend fun callRestService(baseUrl: String): String = withContext(Dispatchers.IO) {
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(RestService::class.java)
try {
val users = service.getUsers()
users.joinToString("\n") { it.toString() }
} catch (e: Exception) {
"Exception: ${e.message}"
}
}
// 调用
lifecycleScope.launch {
val result = callRestService("https://api.example.com/")
Log.d("REST", result)
}
- 说明:
- 使用 Gson 解析 JSON 响应。
- 结合协程简化异步处理。
- 支持 XML 响应(需添加
converter-simplexml
)。
2. 使用 OkHttp 调用 REST WebService
OkHttp 适合需要更灵活控制的场景。
- 代码示例:
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpRestClient {
public static String callRestService(String url) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.get()
.addHeader("Accept", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful() && response.body() != null) {
return response.body().string();
} else {
return "Error: HTTP " + response.code();
}
} catch (Exception e) {
e.printStackTrace();
return "Exception: " + e.getMessage();
}
}
}
- 使用示例(异步调用):
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.example.com/users")
.get()
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
runOnUiThread(() -> Log.e("REST", "Exception: " + e.getMessage()));
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful() && response.body() != null) {
String json = response.body().string();
runOnUiThread(() -> {
Log.d("REST", json);
// 解析 JSON(参考“Android JSON 数据解析”)
});
}
}
});
五、注意事项
- 异步处理:
- 网络操作必须在子线程执行,避免
NetworkOnMainThreadException
。 - 使用 Thread、OkHttp 回调、Retrofit 异步调用或 Kotlin 协程。
- SOAP 特定:
- 获取 WSDL 中的命名空间、方法名和 SOAP Action。
- 使用 kSOAP2 简化 SOAP 请求,减少手动构造 XML 的复杂性。
- 解析 XML 响应(参考“Android XML 数据解析”)。
- REST 特定:
- 确认 API 的请求方法(GET/POST)、参数和响应格式(JSON/XML)。
- 使用 Retrofit + Gson/Moshi 解析 JSON。
- 错误处理:
- 处理 HTTP 状态码(4xx、5xx)。
- 处理
IOException
、SoapFault
(SOAP)或JSONException
(REST)。 - 示例:
java if (responseCode != HttpURLConnection.HTTP_OK) { InputStream errorStream = conn.getErrorStream(); String error = new BufferedReader(new InputStreamReader(errorStream)).lines().collect(Collectors.joining("\n")); Log.e("Error", error); }
- 资源释放:
- 关闭
InputStream
、OutputStream
和HttpURLConnection
。 - OkHttp 和 Retrofit 自动管理连接。
- 安全性:
- 使用 HTTPS 确保数据安全。
- 验证服务器证书,避免信任所有证书。
- 添加认证头(如
Authorization: Bearer token
)。
- 性能优化:
- 使用 Gzip 压缩(
Accept-Encoding: gzip
)。 - 缓存响应数据(参考
Cache-Control
头)。 - 优化 XML/JSON 解析(参考“Android XML/JSON 数据解析”)。
六、学习建议与实践
- 学习路径:
- 了解 SOAP 和 REST WebService 的区别及协议(SOAP 使用 XML,REST 使用 JSON/XML)。
- 掌握 kSOAP2 调用 SOAP WebService。
- 学习 Retrofit 调用 REST WebService。
- 结合 OkHttp 处理复杂请求(如自定义头、进度监听)。
- 解析 XML/JSON 响应(参考“Android XML/JSON 数据解析”)。
- 实践项目:
- SOAP 项目:调用公开 SOAP 服务(如 http://www.webxml.com.cn/ 的天气服务),显示结果。
- REST 项目:调用公开 REST API(如 GitHub API),解析用户数据并显示。
- 综合项目:实现登录功能,调用 REST 或 SOAP 认证接口。
- 调试工具:
- Postman:测试 SOAP/REST API,验证请求/响应。
- SoapUI:专门测试 SOAP WebService,查看 WSDL 和响应。
- Charles/Fiddler:抓包分析 HTTP 请求。
- Android Studio Network Profiler:查看请求详情。
- 推荐资源:
- kSOAP2 文档:https://github.com/simpligility/ksoap2-android
- Retrofit 文档:https://square.github.io/retrofit/
- OkHttp 文档:https://square.github.io/okhttp/
- 公开 API:http://www.webxml.com.cn/(SOAP)、https://api.github.com/(REST)
七、总结
- SOAP WebService:
- 使用 kSOAP2 简化调用,构造 XML 请求,解析 XML 响应。
- 替代方案:
HttpURLConnection
手动构造 SOAP 请求(复杂)。 - REST WebService:
- 使用 Retrofit 简化 API 调用,结合 Gson/Moshi 解析 JSON。
- 替代方案:OkHttp 提供灵活控制。
- 注意事项:异步处理、错误处理、资源释放、HTTPS 安全。
- 推荐:SOAP 使用 kSOAP2,REST 使用 Retrofit + OkHttp。
- 实践:调用公开 WebService,解析响应,显示数据。
如果需要更详细的代码示例(如复杂 SOAP 请求、REST 认证、XML 解析)或特定场景的讲解,请告诉我!