上一篇
安卓开发中网络数据的传送
- 行业动态
- 2025-04-22
- 3
安卓网络数据传输核心要点
网络权限配置
权限类型 | 用途 | 适配说明 |
---|---|---|
INTERNET | 基础网络通信 | 必须在AndroidManifest.xml声明 |
ACCESS_NETWORK_STATE | 网络状态检测 | 可选但推荐声明 |
特殊权限 | 定位/后台流量 | Android 10+需动态申请 |
注意:Android 6.0+需动态申请危险权限,Android 13+强化前台服务限制
基础网络操作模式
// 同步请求(已废弃) URL url = new URL("https://api.example.com/data"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置请求方法/头/超时等参数 InputStream is = conn.getInputStream(); // 读取数据(主线程会阻塞)
典型问题:
- 主线程网络操作会抛出
NetworkOnMainThreadException
- 无法处理复杂业务逻辑
- 用户体验差(白屏/卡顿)
异步处理方案对比
方案 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
AsyncTask | 简单网络请求 | 代码简洁 | 生命周期管理困难 不支持并发 |
HandlerThread | 后台数据处理 | 轻量级 | 需手动管理线程池 |
IntentService | 多任务处理 | 自动回收 | 不适合长时间任务 |
RxJava+OkHttp | 复杂网络流 | 链式调用灵活 | 学习成本较高 |
现代推荐方案:
// Retrofit+协程组合 interface ApiService { @GET("users/{id}") suspend fun getUser(@Path("id") userId: Int): Response<User> } // 在ViewModel中调用 viewModelScope.launch { try { val user = apiService.getUser(123) // 更新UI } catch (e: Exception) { // 错误处理 } }
主流网络库特性
库名称 | 核心功能 | 最佳实践 |
---|---|---|
OkHttp | 高效HTTP请求 | 配合拦截器使用 支持WebSocket |
Retrofit | REST API封装 | 结合Gson/Moshi 动态代理生成接口 |
Volley | 图片加载+小数据 | 适合ListView分页加载 |
Ktor | Kotlin原生客户端 | 支持协程+全平台 |
典型配置示例:
// OkHttp拦截器配置 OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(chain -> { Request request = chain.request().newBuilder() .addHeader("Authorization", "Bearer token") .build(); return chain.proceed(request); }) .build();
数据解析方案
数据类型 | 推荐库 | 性能对比 |
---|---|---|
JSON | Gson/Moshi | Moshi更快 Gson更通用 |
XML | SimpleXML | 性能较差 结构清晰 |
Protobuf | Google官方库 | 二进制格式 高性能 |
Gson使用示例:
Gson gson = new GsonBuilder() .registerTypeAdapter(Date.class, new DateDeserializer()) .create(); MyData data = gson.fromJson(jsonString, MyData.class);
安全加固措施
证书验证:
- 强制使用HTTPS(Android 9+默认)
- 自签名证书处理:
client.sslSocketFactory(getSSLContext().getSocketFactory(), trustManager);
数据加密:
- 敏感数据AES加密
- 使用
SecureRandom
生成密钥 - 避免硬编码密钥(使用Keystore存储)
防抓包策略:
- 启用证书锁定(Certificate Pinning)
- 添加时间戳/签名校验
- 关键接口增加IP白名单
常见问题解决方案
问题现象 | 解决方案 | 代码示例 |
---|---|---|
文件上传失败 | 设置Content-Type 分块上传 | MediaType.parse("multipart/form-data") |
SSL握手异常 | 自定义TrustManager 禁用证书校验(慎用) | hostnameVerifier = (hostname, session) -> true |
内存溢出 | 流式处理响应 设置缓冲区大小 | BufferedSource source = response.body().source() |
DNS劫持 | 使用DoH/DoT协议 自定义DNS解析 | OkHttpClient.dns(new Dns() {…}) |
相关问题与解答
Q1:如何在Retrofit中处理多个BaseUrl?
A:可以使用@Url
注解或动态设置BaseUrl:
// 方法1:通过@Url传递完整路径 @GET Call<ResponseBody> downloadFile(@Url String fileUrl); // 方法2:动态设置BaseUrl Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://default.com/") .build(); ApiService api = retrofit.create(ApiService.class); api.setBaseUrl("https://new.url/"); // 需要自定义实现
Q2:为什么建议在WorkManager中执行网络任务?
A:相比传统后台服务,WorkManager具有以下优势:
- 兼容性:自动适配不同Android版本的后台执行限制
- 可靠性:保证任务最终执行(网络恢复后重试)
- 电池优化:智能选择执行时机(充电/闲置时段)
- 生命周期管理:自动处理应用被杀/设备重启等情况
示例代码:
val uploadWork = OneTimeWorkRequestBuilder<UploadWorker>() .setConstraints(Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build()) .build() WorkManager.getInstance(context).enqueue(uploadWork)