我正在尝试使用OkHttp3库在Amazon S3上传文件。我可以使用ProgressDialog
上传文件。现在,我显示正常ProgressDialog
。但是,我想将ProgressBar
替换为ResponseBody
。为此,我正在做以下事情,但不知何故它不起作用:
1)创建自定义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);
}
:
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}}
答案 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);
}