android retrofit下载进度

标签 android

我是 retrofit 新手。我搜索过但没有找到简单的答案。我想知道如何在通知栏中显示下载进度或至少显示一个进度对话框,其中指定下载文件的进程百分比和大小。 这是我的代码:

public interface ServerAPI {
    @GET
    Call<ResponseBody> downlload(@Url String fileUrl);

    Retrofit retrofit =
            new Retrofit.Builder()
                    .baseUrl("http://192.168.43.135/retro/") 
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

}

public void download(){
    ServerAPI api = ServerAPI.retrofit.create(ServerAPI.class);
    api.downlload("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png").enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            try {
                File path = Environment.getExternalStorageDirectory();
                File file = new File(path, "file_name.jpg");
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                IOUtils.write(response.body().bytes(), fileOutputStream);
            }
            catch (Exception ex){
            }
        }


        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
        }
    });
}

如果可以,请指导我。 谢谢

最佳答案

您需要创建一个特定的 OkHttp 客户端,它将拦截网络请求并发送更新。此客户端应仅用于下载。

首先,您需要一个界面,如下所示:

public interface OnAttachmentDownloadListener {
    void onAttachmentDownloadedSuccess();
    void onAttachmentDownloadedError();
    void onAttachmentDownloadedFinished();
    void onAttachmentDownloadUpdate(int percent);
}

您的下载调用应返回一个 ResponseBody,我们将从中扩展以获取下载进度。

private static class ProgressResponseBody extends ResponseBody {

    private final ResponseBody responseBody;
    private final OnAttachmentDownloadListener progressListener;
    private BufferedSource bufferedSource;

    public ProgressResponseBody(ResponseBody responseBody, OnAttachmentDownloadListener progressListener) {
        this.responseBody = responseBody;
        this.progressListener = progressListener;
    }

    @Override public MediaType contentType() {
        return responseBody.contentType();
    }

    @Override public long contentLength() {
        return responseBody.contentLength();
    }

    @Override public BufferedSource source() {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(source(responseBody.source()));
        }
        return bufferedSource;
    }

    private Source source(Source source) {
        return new ForwardingSource(source) {
            long totalBytesRead = 0L;

            @Override public long read(Buffer sink, long byteCount) throws IOException {
                long bytesRead = super.read(sink, byteCount);

                totalBytesRead += bytesRead != -1 ? bytesRead : 0;

                float percent = bytesRead == -1 ? 100f : (((float)totalBytesRead / (float) responseBody.contentLength()) * 100);

                if(progressListener != null)
                    progressListener.onAttachmentDownloadUpdate((int)percent);

                return bytesRead;
            }
        };
    }
}

然后你需要像这样创建你的 OkHttpClient

public OkHttpClient.Builder getOkHttpDownloadClientBuilder(OnAttachmentDownloadListener progressListener) {
    OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();

    // You might want to increase the timeout
    httpClientBuilder.connectTimeout(20, TimeUnit.SECONDS);
    httpClientBuilder.writeTimeout(0, TimeUnit.SECONDS);
    httpClientBuilder.readTimeout(5, TimeUnit.MINUTES);

    httpClientBuilder.addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            if(progressListener == null) return chain.proceed(chain.request());

        Response originalResponse = chain.proceed(chain.request());
        return originalResponse.newBuilder()
                .body(new ProgressResponseBody(originalResponse.body(), progressListener))
                .build();
        }
    });

    return httpClientBuilder;
}

最后,您只需通过传递新的 OkHttp 客户端,以不同的方式创建 Retrofit 客户端。根据您的代码,您可以使用如下内容:

 public Retrofit getDownloadRetrofit(OnAttachmentDownloadListener listener) {

    return new Retrofit.Builder()
                .baseUrl("http://192.168.43.135/retro/") 
                .addConverterFactory(GsonConverterFactory.create())
                .client(getOkHttpDownloadClientBuilder(listener).build())
                .build();

}

您的监听器将处理您的通知或您想要的任何其他内容的创建。

关于android retrofit下载进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42118924/

相关文章:

Android如何读取存储在包含西类牙字符的 Assets 中的文本文件

java - Android从AsyncTask调用notifyDataSetChanged

java - Eclipse 在一段时间后停止突出显示引用

javascript - Expo MediaLibrary.getAssetsAsync() 在 android 上使应用程序崩溃

android - 如何防止 Holo 主题中的标签栏项目自动换行?

android - 在 android build.gradle 文件中添加任何新的依赖项。它总是显示错误

android - 应用程序是否可以更改 Android 主屏幕?

java - 自定义标记图标谷歌地图android

android - 在真实设备中使用相机 Intent 后,Android Studio崩溃(虚拟模拟器运行正常)

android - 无法使用 Robolectric 4.0.1 运行测试, 'packageDebugUnitTestForUnitTest' 失败