Отображение ProgressBar при загрузке файлов в Android с помощью OkHttp3

Я пытаюсь загрузить файлы в Amazon S3, используя библиотеку OkHttp3. Я могу загружать файлы с помощью AsyncTask. Прямо сейчас я показываю обычный ProgressDialog. Но я хочу заменить ProgressDialog на ProgressBar. Для этого я делаю следующие вещи, но как-то не получается:

1) Создание пользовательских ResponseBody и ProgressListener:

private 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);
}

2) Внедрение интерфейса ProgressListener в AsyncTask с использованием для загрузки файлов:

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, " " + "-------------------------");
                    }
                };

3) Создание клиента OkHttp и передача progressListener, созданного на шаге 2, с помощью сетевого перехватчика:

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();

Но операторы Log.d(), используемые в функции update() для progressListener, никогда не выполняются. Если я смогу распечатать эти операторы журнала, я смогу соответствующим образом обновить индикатор выполнения. Может ли кто-нибудь помочь мне.

Вот полный код, используемый в методе doInBackground AsyncTask:

@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;
}

person user2284140    schedule 13.09.2016    source источник


Ответы (1)


Вы должны сначала включить индикатор выполнения, непосредственно перед вызовом обработки 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);

}
person Alberto Schiabel    schedule 13.09.2016
comment
Почему вы дали такое прямое решение Волей. - person Plain_Dude_Sleeping_Alone; 13.09.2016