1、开启一个服务Service实现后台下载
2、通过线程池管理器实现并行下载数量控制
3、利用广播机制更新UI
4、利用网络请求库Ohttp3进行下载
创建一个下载任务类
/**
* Created by familylove on 2017/4/24.
* 下载文件任务类
*/
public class DownloadFileTask implements Callable<String> {
private File mDownloadFile;
private String mFileSize;
private String mFilePath;
private String mFileName;
private String mDownloadUrl;
private boolean mPause = false;
private DownloadListener mDownloadListener;
public DownloadFileTask(String fileName, String downloadUrl, String filePath, DownloadListener downloadListener) {
this.mFilePath = filePath;
this.mFileName = fileName;
this.mDownloadUrl = downloadUrl;
this.mDownloadListener = downloadListener;
}
@Override
public String call() throws Exception {
if (TextUtils.isEmpty(mFilePath) || TextUtils.isEmpty(mFileName))
return "path or name is empty";
char tempEnd = mFilePath.charAt(mFilePath.length() - 1);
if (tempEnd == '/') {
mDownloadFile = new File(mFilePath + mFileName + ".temp");
} else {
mDownloadFile = new File(mFilePath + File.separator + mFileName + ".temp");
}
if (mDownloadFile.exists()) {
long size = mDownloadFile.length();
mFileSize = "bytes=" + size + "-";
}
//设置输出流.
OutputStream outPutStream = null;
InputStream inputStream = null;
try {
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
Request request = null;
if (!TextUtils.isEmpty(mFileSize)) {
request = new Request.Builder().header("Range", mFileSize).url(mDownloadUrl).build();
} else {
request = new Request.Builder().url(mDownloadUrl).build();
}
Call call = okHttpClient.newCall(request);
//检测是否支持断点续传
Response response = call.execute();
ResponseBody responseBody = response.body();
String responeRange = response.headers().get("Content-Range");
if (responeRange == null || !responeRange.contains(Long.toString(mDownloadFile.length()))) {
//最后的标记为 true 表示下载的数据可以从上一次的位置写入,否则会清空文件数据.
outPutStream = new FileOutputStream(mDownloadFile, false);
} else {
outPutStream = new FileOutputStream(mDownloadFile, true);
}
inputStream = responseBody.byteStream();
//如果有下载过的历史文件,则把下载总大小设为 总数据大小+文件大小 . 否则就是总数据大小
if (TextUtils.isEmpty(mFileSize)) {
if (mDownloadListener != null)
mDownloadListener.downloadTotalSize(mDownloadUrl, responseBody.contentLength());
} else {
if (mDownloadListener != null)
mDownloadListener.downloadTotalSize(mDownloadUrl, responseBody.contentLength() + mDownloadFile.length());
}
int length;
//设置缓存大小
byte[] buffer = new byte[1024];
//开始写入文件
while ((length = inputStream.read(buffer)) != -1) {
if (!mPause) {
outPutStream.write(buffer, 0, length);
if (mDownloadListener != null)
mDownloadListener.onDownloadSize(mDownloadUrl, mDownloadFile.length());
} else {
return null;
}
}
} catch (Exception e) {
if (mDownloadListener!=null)
mDownloadListener.downloadFail(mDownloadUrl);
return null ;
} finally {
if (outPutStream != null) {//清空缓冲区
outPutStream.flush();
outPutStream.close();
}
if (inputStream != null)
inputStream.close();
}
//下载后重命名
mDownloadFile.renameTo(new File(mFilePath+File.separator+mFileName));
//下载完成
if (mDownloadListener != null)
mDownloadListener.onComplete(mDownloadUrl);
return null;
}
//停止下载
public void setPause(boolean pause) {
this.mPause = pause;
}
public interface DownloadListener {
public void downloadTotalSize(String tag, long totalSize);
public void onDownloadSize(String tag, long downloadFileSize);
public void onComplete(String tag);
public void downloadFail(String tag) ;
}
}