1、OkClient.java
public class OkDownload {
private static OkDownload instance;
private Handler mHandler;
private OkHttpClient okHttpClient;
private DownloadInterceptor interceptor = new DownloadInterceptor();
private OkDownload() {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
}
if (mHandler == null) mHandler = new Handler(Looper.getMainLooper());
}
public static OkDownload getInstance() {
if (instance == null) {
synchronized (OkDownload.class) {
if (instance == null) {
instance = new OkDownload();
}
}
}
return instance;
}
public void download(String url, String filePath, DownloadCallback callback) {
download(url, filePath, getFileName(url), callback);
}
public void download(String url, String filePath, String fileName, DownloadCallback callback) {
interceptor.setCallback(mHandler, callback);
Request request = new Request.Builder()
.url(url)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (callback != null) callback.onFailed(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream is = null;
byte[] b = new byte[2048];
int len;
FileOutputStream fos = null;
if (callback != null) mHandler.post(callback::onStart);
try {
is = response.body().byteStream();
File file = new File(filePath, fileName);
fos = new FileOutputStream(file);
while ((len = is.read(b)) != -1) {
fos.write(b, 0, len);
}
fos.flush();
// 如果下載文件成功,第一個參數爲文件的絕對路徑
if (callback != null) mHandler.post(()-> callback.onComplete(file.getAbsolutePath()));
} catch (Exception e) {
if (callback != null) callback.onFailed(e);
} finally {
if (is != null) {
is.close();
}
if (fos != null) {
fos.close();
}
}
}
});
}
private String getFileName(String path) {
int separatorIndex = path.lastIndexOf("/");
return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1);
}
}
2、攔截器
DownloadInterceptor.java
public class DownloadInterceptor implements Interceptor {
private DownloadCallback callback;
private Handler mHandler;
public void setCallback(Handler mHandler, DownloadCallback callback) {
this.callback = callback;
this.mHandler = mHandler;
}
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder()
.body(new DownloadResponse(mHandler, response, callback))
.build();
}
}
3、回調接口
DownloadCallback.java
public interface DownloadCallback {
void onStart();
// unit : kb
void update(long readed, long length);
void onComplete(String absolutePath);
void onFailed(Exception e);
}
4、響應體
DownloadResponse.java
public class DownloadResponse extends ResponseBody {
private Response response;
private Handler mHandler;
private DownloadCallback callback;
public DownloadResponse(Handler mHandler, Response response, DownloadCallback callback) {
this.response = response;
this.callback = callback;
this.mHandler = mHandler;
}
@Override
public MediaType contentType() {
return response.body().contentType();
}
@Override
public long contentLength() {
return response.body().contentLength();
}
@Override
public BufferedSource source() {
return Okio.buffer(new ForwardingSource(response.body().source()) {
private long byteReaded = 0;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long read = super.read(sink, byteCount);
byteReaded += read == -1 ? 0 : read;
if (callback != null) {
mHandler.post(() -> callback.update(byteReaded / 1024, response.body().contentLength() / 1024));
}
return byteReaded;
}
});
}
}