Android断点续传下载:DownloadTask类详解
这段代码是一个继承自AsyncTask的下载任务类DownloadTask,用于在后台执行具体的下载逻辑。主要包括以下几个部分:
- 定义了一系列的下载状态常量,包括下载成功、下载失败、暂停下载、取消下载和错误状态。
public static final int TYPE_SUCCESS = 0;//下载成功
public static final int TYPE_FAILED = 1;//下载失败
public static final int TYPE_PAUSED = 2;//暂停下载
public static final int TYPE_CANCELED = 3;//取消下载
public static final int TYPE_ERROR = 4;
- 定义了一系列的参数,包括DownloadListener监听器、是否取消下载和是否暂停下载的标志位、上一次的下载进度。
private DownloadListener listener;
private boolean isCanceled = false;
private boolean isPaused = false;
private int lastProgress;
- 在构造函数中接收DownloadListener参数,并将其赋值给listener。
public DownloadTask(DownloadListener listener){
this.listener=listener;
}
- 在doInBackground方法中执行具体的下载逻辑。首先获取下载的URL地址和文件名,然后判断文件是否已存在,如果存在则获取已下载的字节数。接着使用OkHttp发送网络请求,通过断点下载的方式从指定字节开始下载文件,并实时计算下载进度并调用publishProgress方法进行通知。最后根据下载的结果返回相应的状态。
@Override
protected Integer doInBackground(String... params) {//用于在后台执行具体的下载逻辑
InputStream is = null;
RandomAccessFile savedFile = null;
File file = null;
try {
long downloadedLength = 0; // 记录已下载的文件长度
String downloadUrl = params[0];//从参数中获取到下载的URL地址
//指定将文件下载到Environment.DIRECTORY_DOWNLOADS目录下,也就是SD卡的Download目录。
String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));//根据URL地址解析出了下载的文件名。
String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();//要下载的目录名
file = new File(directory + fileName);
//判断一下Download目录中是不是已经存在要下载的文件了
if (file.exists()) {//如果已经存在的话则读取已下载的字节数,这样就可以在后面启用断点续传的功能
downloadedLength = file.length();
}
//调用了getContentLength() 方法来获取待下载文件的总长度
long contentLength = getContentLength(downloadUrl);
if (contentLength == 0) {//如果文件长度等于0则说明文件有问题
return TYPE_ERROR;
} else if (contentLength == downloadedLength) {
// 已下载字节和文件总字节相等,说明已经下载完成了
return TYPE_SUCCESS;
}
//紧接着使用OkHttp来发送一条网络请求
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
// 断点下载,指定从哪个字节开始下载(已下载过的部分就不需要下载了)
.addHeader("RANGE", "bytes=" + downloadedLength + "-")//在请求中添加了一个header,用于告诉服务器我们想要从哪个字节开始下载
.url(downloadUrl)
.build();
//接下来读取服务器响应的数据。,并使用Java的文件流方式,
// 不断从网络上读取数据,不断写入到本地,一直到文件全部下载完成为止。
Response response = client.newCall(request).execute();
if (response != null) {
is = response.body().byteStream();
savedFile = new RandomAccessFile(file, "rw");
savedFile.seek(downloadedLength); // 跳过已下载的字节
byte[] b = new byte[1024];
int total = 0;
int len;
while ((len = is.read(b)) != -1) {
//判断用户有没有触发暂定或者取消的操作
if (isCanceled) {
return TYPE_CANCELED;//触发取消
} else if(isPaused) {
return TYPE_PAUSED;//触发暂停
} else {
total += len;
savedFile.write(b, 0, len);
// 计算已下载的百分比(实时计算当前的下载进度)
int progress = (int) ((total + downloadedLength) * 100 /
contentLength);
//调用publishProgress() 方法进行通知
publishProgress(progress);
}
}
response.body().close();
return TYPE_SUCCESS;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (savedFile != null) {
savedFile.close();
}
if (isCanceled && file != null) {
file.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return TYPE_FAILED;
}
- 定义了getContentLength方法用于获取待下载文件的总长度。
private long getContentLength(String downloadUrl) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(downloadUrl)
.build();
Response response = client.newCall(request).execute();
if (response != null && response.isSuccessful()) {
long contentLength = response.body().contentLength();
response.body().close();
return contentLength;
}
return 0;
}
- 在onProgressUpdate方法中更新下载进度,通过调用DownloadListener的onProgress方法进行通知。
@Override
protected void onProgressUpdate(Integer... values) {
int progress = values[0];//首先从参数中获取到当前的下载进度
if (progress > lastProgress) {//和上一次的下载进度进行对比
//如果有变化的话则调用DownloadListener的onProgress() 方法来通知下载进度更新。
listener.onProgress(progress);
lastProgress = progress;
}
}
- 在onPostExecute方法中根据下载状态调用相应的方法进行通知。
@Override
protected void onPostExecute(Integer status) {//根据参数中传入的下载状态来进行回调
switch (status) {//对应不同状态就调用不同的方法
case TYPE_SUCCESS:
listener.onSuccess();
break;
case TYPE_FAILED:
listener.onFailed();
break;
case TYPE_PAUSED:
listener.onPaused();
break;
case TYPE_CANCELED:
listener.onCanceled();
break;
default:
break;
}
}
- 定义了pauseDownload和cancelDownload方法用于暂停和取消下载,通过修改isPaused和isCanceled的值来控制下载的暂停和取消。
public void pauseDownload() {
isPaused = true;
}
public void cancelDownload() {
isCanceled = true;
}
这段代码的实验结果是,通过DownloadTask类实现了具体的下载逻辑,并通过DownloadListener接口进行下载进度和状态的回调通知。可以根据需要进行暂停和取消下载操作。
原文地址: https://gggwd.com/t/topic/L8h 著作权归作者所有。请勿转载和采集!