- 使用okHttp3实现下载文件进度监听之踩坑
·
在build.gradle中引入okhttp3
implementation 'com.squareup.okhttp3:okhttp:4.4.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.4.0'
- 代码实现
/**
* 下载文件
*
* @param url 下载地址
* @param fileName 保存的文件名 文件路径 load
*/
public static void loadFile(String url, String fileName, final OnDownloadListener listener) {
String filePath = "load";
String absoluteFilePath = Environment.getExternalStorageDirectory().toString()
+ File.separator + filePath + File.separator
+ fileName;
final File file = new File(absoluteFilePath);
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
Request request = new Request.Builder().url(url).build();
if (listener != null) {
listener.onDownloadStart();
}
getLoadFileOkHttp().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (listener != null) {
listener.onDownloadFailed();
}
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (200 == response.code()) {
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
try {
long total = response.body().contentLength();
long sum = 0;
inputStream = response.body().byteStream();
fileOutputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024 * 1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
if (listener != null) {
sum += len;
int progress = (int) (sum * 1.0f / total * 100);
// 下载中
listener.onDownloading(progress);
}
}
fileOutputStream.flush();
if (listener != null) {
listener.onDownloadSuccess(absoluteFilePath);
}
} catch (IOException e) {
if (listener != null) {
listener.onDownloadFailed();
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
}
} else {
if (listener != null) {
listener.onDownloadFailed();
}
}
}
});
}
/**
* 监听下载进度回调接口
*/
public interface OnDownloadListener {
/**
* 开始下载
*/
void onDownloadStart();
/**
* 下载成功
* @param filePath 文件下载的路径
*/
void onDownloadSuccess(String filePath);
/**
* @param progress 下载进度
*/
void onDownloading(int progress);
/**
* 下载失败
*/
void onDownloadFailed();
}
private static OkHttpClient mOkHttpClient;
/**
* 初始化 OkHttpClient
*/
public static OkHttpClient getLoadFileOkHttp() {
if (mOkHttpClient == null) {
File sdcache = VApp.getApp().getCacheDir();
int cacheSize = 10 * 1024 * 1024;
mOkHttpClient = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize))
.build();
}
return mOkHttpClient;
}
以上代码实现是可以正常监听到下载文件的进度,但如果在初始化OkHttpClient 时设置了log拦截器,不管拦截器的级别是什么,监听到的进度都不正常(文件已经在开始下载,但没有进度回调,文件下载一段时间后才有进度)
- 以下是初始化 OkHttpClient 使用Log拦截器
private static OkHttpClient mOkHttpClient;
/**
* 初始化 OkHttpClient 带有Log拦截器
*/
public static OkHttpClient getLoadFileOkHttp() {
if (mOkHttpClient == null) {
// log拦截器
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
} else {
interceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
}
File sdcache = VApp.getApp().getCacheDir();
int cacheSize = 10 * 1024 * 1024;
mOkHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize))
.build();
}
return mOkHttpClient;
}