前言:在这里完成了一个完整的从服务器上下载数据的实例!
一、我使用的时OkHttp进行网络通信,所以首先在gradle的dependencies中添加如下依赖:
compile 'com.squareup.okhttp3:okhttp:3.4.1'
二、定义一个进行回调的接口,因为在下载过程中我们会遇到下载成功、失败、暂停、取消等问题,所以先写好这个接口,到时候可以直接进行调用:
/**
* 定义一个回调接口,用于对下载过程中的各种状态进行监听和回调
*/
public interface DownloadListener {
void onProgress(int progress);//通知当前的下载进度
void onSuccess();//通知下载成功
void onFailed();//。。。。失败
void onPaused();//。。。。。暂停
void onCanceled();//。。。。取消
}
三、接口写好后,我们就可以编写下载功能的代码了,代码中有详细的注释!新建一个DownloadTask继承自AsyncTask,
/**
* 下载任务,第一个泛型参数String是指传一个字符串参数给后台,也就是Url;
* 第二个泛型参数Integer,是指使用整型数据作为进度显示单位,也就是显示下载进度条
* 第三个泛型参数是Integer,表示使用整型数据反馈结果
*/
public class DownloadTask extends AsyncTask<String,Integer,Integer> {
//4个整型常量用于表示下载的状态
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;
private DownloadListener listener;
private boolean isCanceled=false;
private boolean isPaused=false;
private int lastProgress;
//在构造函数中传入一个刚刚定义的DownLoadListener参数,待会用这个参数进行下载状态的回调
public DownloadTask(DownloadListener listener){
this.listener=listener;
}
//doInBackground方法用于在后台执行具体的下载逻辑
@Override
protected Integer doInBackground(String... params) {
InputStream is=null;
RandomAccessFile savedFile=null;
File file=null;
try {
long downloadedLength=0;//记录已下载的文件的长度
//获取到下载的URL地址
String downloadUrl=params[0];//下载地址
//根据URL解析出下载的文件名
String fileName=downloadUrl.substring(downloadUrl.lastIndexOf("/"));
//将文件下载到Environment.DIRECTORY_DOWNLOADS目录下,也就是SD卡的Download目录
String directory= Environment.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS).getPath();
file=new File(directory+fileName);
//判断目录中是否已经存在要下载的文件
if (file.exists()){
//如果已经存在,则读取已下载的字节数,这样就可以在后面使用断点续传的功能
downloadedLength=file.length();
}
//使用get。。方法来获取待下载文件的总长度
long contentLength=getContentLength(downloadUrl);
//若文件长度=0,则文件有问题,直接返回下载失败
if (contentLength==0){
return TYPE_FAILED;
//若文件长度=已经下载的文件的长度
}else if (contentLength==downloadedLength){
//已下载的字节和文件总字节相同,则下载成功
return TYPE_SUCCESS;
}
//建立网络链接
OkHttpClient client=new OkHttpClient();
//要发起一个http请求,首先创建一个Request对象
Request request=new Request.Builder()
//断点下载,这里添加了一个header,指定从那个字节开始下载,因为已经下载过的就不要下载了
.addHeader("RANGE","bytes="+downloadedLength+"-")
.url(downloadUrl)
.build();
//调用Okhttp的newCal