Vla*_*rov 2 android file-upload okhttp retrofit2
我有一个可以录制和上传视频文件的应用程序。我有一个记录onFailure Throwable每个文件上传的机制。
我注意到,在使用该应用程序的一千台设备中,有一些设备经常超时并且上传成功率很低。
有问题的设备是:Asus ZenPad C 7.0 Z170C
我已经购买了该设备并开始对其进行测试,但首先让您了解一下我使用的代码。
活动中:
FileUploadService service = ServiceGenerator.createService(FileUploadService.class);
File file = new File(getRealPathFromURI(mediaForUpload.mediaUri));
ProgressRequestBody fileBody = new ProgressRequestBody(file,
new ProgressRequestBody.UploadCallbacks() {
@Override
public void onProgressUpdate(int uploadPercentage) {
// set current progress
}
@Override
public void onError() {}
@Override
public void onFinish() {}
});
MultipartBody.Part body = MultipartBody.Part.createFormData(mediaForUpload.mediaNameWithExtension, mediaForUpload.mediaNameWithExtension, fileBody);
Call<ResponseBody> call = service.upload(body);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
if (response.isSuccessful()) {
} else {
//Log
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//Log
}
});
Run Code Online (Sandbox Code Playgroud)
在服务生成器中:
public static <S> S createService(Class<S> serviceClass) {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.build();
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl("https://some.nice.api/")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.client(client).build();
return retrofit.create(serviceClass);
}
Run Code Online (Sandbox Code Playgroud)
在文件上传服务中:
@Multipart
@POST("/somepath")
Call<ResponseBody> upload(@Part MultipartBody.Part file);
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我的超时时间是 120 秒,这很有趣,但这不足以成功上传 15MB 的视频文件而不超时。
我在华硕 Zenpad C 7.0和三星 Tab 3 7"上进行了几次测试,只是为了向您展示差异。(测试在 2.4GHz 网络上,距离路由器 5 米;Tab 3 平均上传速度:1MB/s, Zenpad C7平均上传速度:~30KB/s(如果奇迹发生)
Android 监视器的屏幕截图:
我测试了OkHttp3 Multipart upload,只是为了确定这不是Retrofit 2问题并且结果是相同的。
经过两天的查找更多信息,我发现了问题所在。
首先,您必须知道默认套接字工厂的 getSendBufferSize() 为 524288。在我们的例子中,对于Asus Zenpad C 7.0来说这已经很多了。
我寻找解决方案的步骤是:
https://github.com/square/okhttp/issues/1078
并实施RestrictedSocketFactory https://gist.github.com/slightfoot/00a26683ea68856ceb50e26c7d8a47d0
之后我对我的代码做了一些修改:
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.socketFactory(new RestrictedSocketFactory(bufferSize))
.build();
Run Code Online (Sandbox Code Playgroud)
我bufferSize的插座与我的插座sendBufferSize尺寸相同。我已经用 256*1024 和 128*1024 进行了测试,C 7.0 的最佳分辨率是 128*1024。不幸的是,所有其他设备的上传速度降低了约 30%,因此我制定了一种机制,仅将这些更改应用于几个设备。(根据我的测试,所有其他设备的最佳分辨率是 256*1024和)DEFAULT_BUFFER_SIZEProgressRequestBodybufferSizeDEFAULT_BUFFER_SIZE
这是使用Asus Zenpad C 7.0上传 17MB 视频文件的图片,您可以看到与第一篇文章的区别。