2016-09-13 52 views
0

我正尝试使用OkHttp3库在Amazon S3中上传文件。我可以使用AsyncTask上传文件。现在,我正在显示一个正常的ProgressDialog。但是,我想用ProgressBar替换ProgressDialog。对于这一点,我做下面的事情,但不知何故,它不工作:在使用OkHttp3在Android中上传文件时显示ProgressBar

1)创建一个自定义ResponseBodyProgressListener

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)使用上传实施的AsyncTask内ProgressListener接口文件:

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客户端,并使用网络拦截传递步骤2中创建的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(); 

但是,progressListener的“update()”函数中使用的Log.d()语句从未得到执行。 如果我可以打印这些日志语句,那么我可以相应地更新进度条。有人能帮助我吗?

这里是的AsyncTask的“doInBackground”方法所使用的全码:

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

回答

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

} 
+0

你为什么作出这样的直排球的解决方案。 –

相关问题