使用OkHttp3在Android中上传文件时显示ProgressBar

时间:2016-09-13 18:22:49

标签: android rest amazon-s3 android-asynctask okhttp3

我正在尝试使用OkHttp3库在Amazon S3上传文件。我可以使用ProgressDialog上传文件。现在,我显示正常ProgressDialog。但是,我想将ProgressBar替换为ResponseBody。为此,我正在做以下事情,但不知何故它不起作用:

1)创建自定义ProgressListenerprivate static class ProgressResponseBody extends ResponseBody { private final ResponseBody responseBody; private final ProgressListener progressListener; private BufferedSource bufferedSource; public ProgressResponseBody(ResponseBody responseBody, ProgressListener 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); // read() returns the number of bytes read, or -1 if this source is exhausted. totalBytesRead += bytesRead != -1 ? bytesRead : 0; progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1); return bytesRead; } }; } } interface ProgressListener { void update(long bytesRead, long contentLength, boolean done); }

final ProgressListener progressListener = new ProgressListener() {
                    @Override
                    public void update(long bytesRead, long contentLength, boolean done) {
                        Log.d(AppGlobal.TAG, " " + bytesRead);
                        Log.d(AppGlobal.TAG, " " + contentLength);
                        Log.d(AppGlobal.TAG, " " + done);
                        Log.d(AppGlobal.TAG, (100 * bytesRead) / contentLength + " % done ");
                        Log.d(AppGlobal.TAG, " " + "-------------------------");
                    }
                };

2)在AsyncTask中实现ProgressListener接口,用于上传文件:

Request request = new Request.Builder()
                        .header("Proxy-Authorization", "Basic " +     Base64.encodeToString(data, Base64.NO_WRAP))
                        .addHeader("Content-Type", "application/octet-stream")
                        .addHeader("Connection", "Keep-Alive")
                        .url(url)
                        .put(RequestBody.create(MediaType.parse("application/octet-stream"), file))
                        .build();

OkHttpClient client = new OkHttpClient.Builder()
                        .connectTimeout(1000, TimeUnit.SECONDS)
                        .writeTimeout(1000, TimeUnit.SECONDS)
                        .readTimeout(3000, TimeUnit.SECONDS)
                        .proxy(proxy)
                        .proxyAuthenticator(proxyAuthenticator)
                        .addNetworkInterceptor(new Interceptor() {
                            @Override public okhttp3.Response intercept(Chain chain) throws IOException {
                                okhttp3.Response originalResponse = chain.proceed(chain.request());
                                return originalResponse.newBuilder()
                                        .body(new ProgressResponseBody(originalResponse.body(), progressListener))
                                        .build();
                            }
                        })
                        .build();

okhttp3.Response response = client.newCall(request).execute();

3)创建一个OkHttp客户端并使用网络拦截器传递在步骤2中创建的progressListener:

@Override
protected Void doInBackground(File... inputs) {
try {
    file = inputs[0];
    Date expiration = new Date();
    long milliSeconds = expiration.getTime();
    milliSeconds += 1000 * 60 * 60; // Add 1 hour.
    expiration.setTime(milliSeconds);


    GeneratePresignedUrlRequest generatePresignedUrlRequest =
            new GeneratePresignedUrlRequest(Constants.BUCKET_NAME, AppGlobal.deviceId + "/" + file.getName());
    generatePresignedUrlRequest.setMethod(HttpMethod.PUT);

    generatePresignedUrlRequest.setContentType("application/octet-stream");

    generatePresignedUrlRequest.setExpiration(expiration);

    final URL url = Util.getS3Client(UploadActivity.this).generatePresignedUrl(generatePresignedUrlRequest);

    Log.d("DXXXXXX", " URL    ->    " + url);

    String domain = AppGlobal.getDomain(UploadActivity.this);
    int port = Integer.valueOf(AppGlobal.getPort(UploadActivity.this));
    final String signature = AppGlobal.getSignature(UploadActivity.this);


    Proxy proxy = new Proxy(Proxy.Type.HTTP,
            InetSocketAddress.createUnresolved(domain, port));//the proxy server(Can be your laptop ip or company proxy)

    try {

        String headerVal = String.format("%s:%s", "vzServices", signature);
        final byte[] data = headerVal.getBytes("UTF-8");

        okhttp3.Authenticator proxyAuthenticator = new okhttp3.Authenticator() {
            @Override
            public Request authenticate(Route route, okhttp3.Response response) throws IOException {

                String credential = Credentials.basic("vzServices", signature);
                return response.request().newBuilder().header("Proxy-Authorization", credential).build();
            }
        };


        final ProgressListener progressListener = new ProgressListener() {
            @Override
            public void update(long bytesRead, long contentLength, boolean done) {
                Log.d(AppGlobal.TAG, " " + bytesRead);
                Log.d(AppGlobal.TAG, " " + contentLength);
                Log.d(AppGlobal.TAG, " " + done);
                Log.d(AppGlobal.TAG, (100 * bytesRead) / contentLength + " % done ");
                Log.d(AppGlobal.TAG, " " + "-------------------------");
            }
        };


        Request request = new Request.Builder()
                .header("Proxy-Authorization", "Basic " + Base64.encodeToString(data, Base64.NO_WRAP))
                .addHeader("Content-Type", "application/octet-stream")
                .addHeader("Connection", "Keep-Alive")
                .url(url)
                .put(RequestBody.create(MediaType.parse("application/octet-stream"), file))
                .build();

        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(1000, TimeUnit.SECONDS)
                .writeTimeout(1000, TimeUnit.SECONDS)
                .readTimeout(3000, TimeUnit.SECONDS)
                .proxy(proxy)
                .proxyAuthenticator(proxyAuthenticator)
                .addNetworkInterceptor(new Interceptor() {
                    @Override public okhttp3.Response intercept(Chain chain) throws IOException {
                        okhttp3.Response originalResponse = chain.proceed(chain.request());
                        return originalResponse.newBuilder()
                                .body(new ProgressResponseBody(originalResponse.body(), progressListener))
                                .build();
                    }
                })
                .build();

        okhttp3.Response response = client.newCall(request).execute();

        responseCode = response.code();
        Log.d("Response code : ", " " + response.code());
        Log.d("DXXXXXX", " URL  1  ->    " + url);
        success = true;
        buffer = null;

    } catch (Exception ex) {
        // Handle the error
        Log.d(TAG, "Error: " + ex.getLocalizedMessage());
        ex.printStackTrace();
    }


} catch (Exception e) {

    e.printStackTrace();
}
return null;
}

但是,progressListener的“update()”函数中使用的Log.d()语句永远不会被执行。 如果我可以打印这些Log语句,那么我可以相应地更新进度条。有人可以帮助我。

以下是AsyncTask的“doInBackground”方法中使用的完整代码:

{{1}}

1 个答案:

答案 0 :(得分:0)

您应该在调用okhttp3处理之前首先启用进度条。然后,在回复和出错时,你应该解雇它。 这是片段(我不知道okhttp,但我已多次使用凌空。这个例子很简单,让你明白我的意思。)

sendJsonRequest(){

 //enable progress bar here
enableProgressBar();        
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, URL, null,

new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
    // dismiss it
     hideProgressDialog();  
     System.out.println(response);
 }
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
     // dismiss it and/or handle errors
     hideProgressDialog();
     // ...
}
});
queue.add(jsObjRequest);

}