Retrofit 2真机提交请求失败仅模拟器可用问题求助
Retrofit 2 上传请求在API24真机失败的排查方案
看起来你遇到了一个很典型的「模拟器正常、真机翻车」的适配问题,我来帮你一步步拆解可能的原因和解决办法:
1. 先查明文网络限制(API24+的坑)
Android 7.0(API24)开始默认禁止明文HTTP请求,模拟器因为调试环境宽松可能没触发这个限制,但真机严格执行了策略。如果你的上传接口是HTTP而非HTTPS,直接就会被拦截进onFailure。
解决办法:
- 优先把接口升级为HTTPS(最稳妥);
- 若暂时无法升级,可添加网络安全配置:
在res/xml目录下创建network_security_config.xml,内容如下:
然后在<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>AndroidManifest.xml的application标签里添加:android:networkSecurityConfig="@xml/network_security_config"
2. 检查文件读取权限与路径有效性
真机的文件权限管控比模拟器严格得多:
- 如果你读取的是外部存储文件(比如相册、下载目录),API24+需要动态申请
READ_EXTERNAL_STORAGE权限,光在Manifest里声明没用; - 确认你传入Retrofit的
File对象真实存在且可读:可以在上传前加个判断:File uploadFile = new File(filePath); if (!uploadFile.exists() || !uploadFile.canRead()) { Log.e("UploadCheck", "文件不存在或无法读取"); return; }
3. 核对Multipart请求的注解配置
上传文件+字符串的Multipart请求很容易踩注解的坑,比如参数名写错、注解类型用错:
- 正确的接口定义示例:
@Multipart @POST("你的上传接口路径") Call<ResponseBody> uploadData( @Part("name") RequestBody nameBody, @Part("des") RequestBody desBody, @Part MultipartBody.Part filePart); - 构建RequestBody时,文件的MediaType要匹配实际文件类型(比如图片用
MediaType.parse("image/jpeg"),文档用MediaType.parse("application/pdf")),类型不匹配可能被服务器拒绝,真机的网络环境更容易触发这个问题。
4. 必做:打印onFailure的详细错误信息
这是最快定位问题的方法!在onFailure回调里把异常信息打出来:
@Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.e("UploadFail", "请求失败原因", t); // 或者直接打印t.getMessage()看关键信息 Toast.makeText(context, "失败:" + t.getMessage(), Toast.LENGTH_SHORT).show(); }
比如:
- 如果是
SSLHandshakeException:HTTPS证书不被信任; - 如果是
FileNotFoundException:文件路径或权限有问题; - 如果是
ConnectException:真机网络无法连接到服务器(比如代理、防火墙限制)。
5. 排查真机的网络环境
模拟器用的是电脑的网络,可能没有真机的网络限制:
- 检查真机是否连接了正常的WiFi/移动数据,能不能用浏览器直接访问你的上传接口;
- 如果你在公司内网,真机可能需要配置代理才能访问服务器,而模拟器默认继承了电脑的代理。
内容的提问来源于stack exchange,提问作者hosein2rd
相关产品推荐
相关产品推荐

