FileDownloader,开源库
https://github.com/lingochamp/FileDownloader
- 特点
- 简单易用
- 单任务多线程/多连接/分块下载(并支持通过ConnectionCountAdapter定制)
- 高并发
- 灵活
- 可选择性支持: 独立/非独立进程
- 自动断点续传
需要注意
当下载的文件大小可能大于1.99GB(2^31-1=2_147_483_647 = 1.99GB)的时候, 请使用FileDownloadLargeFileListener而不是FileDownloadListener(同理使用getLargeFileSofarBytes()
与getLargeFileTotalBytes()
暂停: paused, 恢复: 直接调用start,默认就是断点续传引擎默认会打开避免掉帧的处理(使得在有些情况下回调(FileDownloadListener)不至于太频繁导致ui线程被ddos), 如果你希望关闭这个功能(关闭以后,所有回调会与0.1.9之前的版本一样,所有的回调会立马抛一个消息ui线(Handler))如果没有特殊需要,直接通过配置filedownloader.properties将process.non-separate置为true,可以有效减少每次回调IPC带来的I/O。
官方演示文档:
确实蛮不错的,但是根据官方开源库的文档撸代码,发现还是有很多行不通的地方,这里建议github库的作者还是完善完善说明文档
贴一下自己写的代码;
实现步骤
权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
1.在项目中引用库:
compile 'com.liulishuo.filedownloader:library:1.6.4'
2.初始化:
FileDownloader.setup(getApplicationContext());
3.下载
final ViewHolder tag;
final String url;
boolean isDir = false;
String path;
url = "http://cdn.llsapp.com/android/LLS-v4.0-595-20160908-143200.apk";
tag = new ViewHolder(new WeakReference<>(this), progressBar1, null, speedTv1, 1);
path = llsApkFilePath;
tag.setFilenameTv(filenameTv1);
FileDownloader.getImpl().create(url)
.setPath(path, isDir)
.setCallbackProgressTimes(300)
.setMinIntervalUpdateSpeed(400)
.setTag(tag)
.setListener(new FileDownloadSampleListener() {
@Override
protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
super.pending(task, soFarBytes, totalBytes);
((ViewHolder) task.getTag()).updatePending(task);
}
@Override
protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
super.progress(task, soFarBytes, totalBytes);
((ViewHolder) task.getTag()).updateProgress(soFarBytes, totalBytes,
task.getSpeed());
down_sumber.setText("下載進程: "+soFarBytes/1024/1024+"MB / "+totalBytes/1024/1024+"MB");
}
@Override
protected void error(BaseDownloadTask task, Throwable e) {
super.error(task, e);
((ViewHolder) task.getTag()).updateError(e, task.getSpeed());
}
@Override
protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {
super.connected(task, etag, isContinue, soFarBytes, totalBytes);
((ViewHolder) task.getTag()).updateConnected(etag, task.getFilename());
}
@Override
protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
super.paused(task, soFarBytes, totalBytes);
((ViewHolder) task.getTag()).updatePaused(task.getSpeed());
}
@Override
protected void completed(BaseDownloadTask task) {
super.completed(task);
((ViewHolder) task.getTag()).updateCompleted(task);
}
@Override
protected void warn(BaseDownloadTask task) {
super.warn(task);
((ViewHolder) task.getTag()).updateWarn();
}
});
}
4.ViewHolder的类
private static class ViewHolder {
private ProgressBar progressBar1;
private TextView detailTv;
private TextView speedTv;
private int position;
private TextView filenameTv;
private WeakReference<http_down> weakReferenceContext;
public ViewHolder(WeakReference<http_down> weakReferenceContext,
final ProgressBar progressBar1, final TextView detailTv, final TextView speedTv,
final int position) {
this.weakReferenceContext = weakReferenceContext;
this.progressBar1 = progressBar1;
this.detailTv = detailTv;
this.position = position;
this.speedTv = speedTv;
}
public void setFilenameTv(TextView filenameTv) {
this.filenameTv = filenameTv;
}
private void updateSpeed(int speed) {
speedTv.setText(String.format("速度: %dKB/s", speed));
}
public void updateProgress(final int sofar, final int total, final int speed) {
if (total == -1) {
// chunked transfer encoding data
progressBar1.setIndeterminate(true);
} else {
progressBar1.setMax(total);
progressBar1.setProgress(sofar);
}
updateSpeed(speed);
if (detailTv != null) {
detailTv.setText(String.format("sofar: %d total: %d", sofar, total));
}
}
public void updatePending(BaseDownloadTask task) {
if (filenameTv != null) {
filenameTv.setText("名稱 :"+task.getFilename());
}
}
public void updatePaused(final int speed) {
toast(String.format("已停止下載 ", position));
updateSpeed(speed);
progressBar1.setIndeterminate(false);
}
public void updateConnected(String etag, String filename) {
if (filenameTv != null) {
filenameTv.setText("名稱 :"+filename);
}
}
public void updateWarn() {
toast(String.format("warn %d", position));
progressBar1.setIndeterminate(false);
}
public void updateError(final Throwable ex, final int speed) {
toast(String.format("error %d %s", position, ex));
updateSpeed(speed);
progressBar1.setIndeterminate(false);
ex.printStackTrace();
}
public void updateCompleted(final BaseDownloadTask task) {
toast(String.format("下載完成,下載路徑 %d %s", position, task.getTargetFilePath()));
if (detailTv != null) {
detailTv.setText(String.format("sofar: %d total: %d",
task.getSmallFileSoFarBytes(), task.getSmallFileTotalBytes()));
}
updateSpeed(task.getSpeed());
// progressBar1.setIndeterminate(false);
progressBar1.setMax(task.getSmallFileTotalBytes());
progressBar1.setProgress(task.getSmallFileSoFarBytes());
}
private void toast(final String msg) {
if (this.weakReferenceContext != null && this.weakReferenceContext.get() != null) {
Snackbar.make(weakReferenceContext.get().down, msg, Snackbar.LENGTH_LONG).show();
}
}
5.停止
FileDownloader.getImpl().pause(downloadId1);
6.删除
new File(llsApkFilePath).delete();
new File(FileDownloadUtils.getTempPath(llsApkFilePath)).delete();