FileDownloader 库推荐
来源:互联网 发布:conoha装windows 编辑:程序博客网 时间:2024/04/29 11:12
FileDownloader
Android 文件下载引擎,稳定、高效、简单易用
README DOC
本引擎依赖okhttp 3.2.0
版本迭代日志: Change Log
英文文档: Wiki
特点
- 简单易用
- 高并发
- 可选择性支持: 独立/非独立进程
- 自动断点续传
需要注意
- 当下载的文件大小可能大于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。
使用okHttp并使用其中的一些默认属性
- retryOnConnectionFailure: Unreachable IP addresses/Stale pooled connections/Unreachable proxy servers
- connection/read/write time out 10s
欢迎提交 Pull requests
- 尽量多的英文注解。
- 每个提交尽量的细而精准。
- Commit message 遵循: AngularJS's commit message convention。
- 尽可能的遵循IDE的代码检查建议(如 Android Studio 的 'Inspect Code')。
I. 效果
II. 使用
在项目中引用:
compile 'com.liulishuo.filedownloader:library:0.2.8'
全局初始化在Application.onCreate
中
如果希望定制化用于下载的
OkHttpClient
,建议参考DemoApplication
public XXApplication extends Application{ ... @Override public void onCreate() { /** * 仅仅是缓存Application的Context,不耗时 */ FileDownloader.init(getApplicationContext); } ...}
启动单任务下载
FileDownloader.getImpl().create(url) .setPath(path) .setListener(new FileDownloadListener() { @Override protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) { } @Override protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) { } @Override protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) { } @Override protected void blockComplete(BaseDownloadTask task) { } @Override protected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) { } @Override protected void completed(BaseDownloadTask task) { } @Override protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) { } @Override protected void error(BaseDownloadTask task, Throwable e) { } @Override protected void warn(BaseDownloadTask task) { } }).start();
启动多任务下载
final FileDownloadListener queueTarget = new FileDownloadListener() { @Override protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) { } @Override protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) { } @Override protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) { } @Override protected void blockComplete(BaseDownloadTask task) { } @Override protected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) { } @Override protected void completed(BaseDownloadTask task) { } @Override protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) { } @Override protected void error(BaseDownloadTask task, Throwable e) { } @Override protected void warn(BaseDownloadTask task) { }};// 第一种方式 ://for (String url : URLS) {// FileDownloader.getImpl().create(url)// .setCallbackProgressTimes(0) // 由于是队列任务, 这里是我们假设了现在不需要每个任务都回调`FileDownloadListener#progress`, 我们只关系每个任务是否完成, 所以这里这样设置可以很有效的减少ipc.// .setListener(queueTarget)// .ready();//}//if(serial){ // 串行执行该队列// FileDownloader.getImpl().start(queueTarget, true);// }// if(parallel){ // 并行执行该队列// FileDownloader.getImpl().start(queueTarget, false);//}// 第二种方式:final FileDownloadQueueSet queueSet = new FileDownloadQueueSet(downloadListener);final List<BaseDownloadTask> tasks = new ArrayList<>();for (int i = 0; i < count; i++) { tasks.add(FileDownloader.getImpl().create(Constant.URLS[i]).setTag(i + 1));}queueSet.disableCallbackProgressTimes(); // 由于是队列任务, 这里是我们假设了现在不需要每个任务都回调`FileDownloadListener#progress`, 我们只关系每个任务是否完成, 所以这里这样设置可以很有效的减少ipc.// 所有任务在下载失败的时候都自动重试一次queueSet.setAutoRetryTimes(1);if (serial) { // 串行执行该任务队列 queueSet.downloadSequentially(tasks); // 如果你的任务不是一个List,可以考虑使用下面的方式,可读性更强// queueSet.downloadSequentially(// FileDownloader.getImpl().create(url).setPath(...),// FileDownloader.getImpl().create(url).addHeader(...,...),// FileDownloader.getImpl().create(url).setPath(...)// );}if (parallel) { // 并行执行该任务队列 queueSet.downloadTogether(tasks); // 如果你的任务不是一个List,可以考虑使用下面的方式,可读性更强// queueSet.downloadTogether(// FileDownloader.getImpl().create(url).setPath(...),// FileDownloader.getImpl().create(url).setPath(...),// FileDownloader.getImpl().create(url).setSyncCallback(true)// );}
全局接口说明(FileDownloader
)
所有的暂停,就是停止,会释放所有资源并且停到所有相关线程,下次启动的时候默认会断点续传
Task接口说明
If-Match
与Range
参数),请勿重复添加导致400或其他错误addHeader(line:String)添加自定义的请求头参数,需要注意的是内部为了断点续传,在判断断点续传有效时会自动添加上(If-Match
与Range
参数),请勿重复添加导致400或其他错误setMinIntervalUpdateSpeed(minIntervalUpdateSpeedMs:int)设置下载中刷新下载速度的最小间隔removeAllHeaders(name:String)删除由自定义添加上去请求参数为{name}
的所有键对ready(void)用于队列下载的单任务的结束符(见上面:启动多任务下载的案例)start(void)启动下载任务pause(void)暂停下载任务(也可以理解为停止下载,但是在start的时候默认会断点续传)getId(void):int获取唯一Id(内部通过url与path生成)getUrl(void):String获取下载连接getCallbackProgressTimes(void):int获得progress最大回调次数getPath(void):String获取下载文件存储路径getListener(void):FileDownloadListener获取监听器getSoFarBytes(void):int获取已经下载的字节数getTotalBytes(void):int获取下载文件总大小getStatus(void):int获取当前的状态isForceReDownload(void):boolean是否强制重新下载getEx(void):Throwable获取下载过程抛出的ThrowableisReusedOldFile(void):boolean判断是否是直接使用了旧文件(检测是有效文件),没有启动下载getTag(void):Object获取用户setTag进来的ObjectgetTag(key:int):Object根据key获取存储在task中的变量isContinue(void):boolean是否成功断点续传getEtag(void):String获取当前下载获取到的ETaggetAutoRetryTimes(void):int自动重试次数getRetryingTimes(void):int当前重试次数。将要开始重试的时候,会将接下来是第几次isSyncCallback(void):boolean是否是设置了所有FileDownloadListener中的回调都直接在下载线程直接回调而不抛到ui线程getSpeed():int获取任务的下载速度, 下载过程中为实时速度,下载结束状态为平均速度监听器(FileDownloadListener
)说明
一般的下载回调流程:
pending -> started -> connected -> (progress <->progress) -> blockComplete -> completed
可能会遇到以下回调而直接终止整个下载过程:
paused / completed / error / warn
如果检测存在已经下载完成的文件(可以通过isReusedOldFile
进行决策是否是该情况)(也可以通过setForceReDownload(true)
来避免该情况):
blockComplete -> completed
方法说明
由于FileDownloadListener
中的方法回调过快,导致掉帧?
你有两种方法可以解决这个问题
FileDownloader#enableAvoidDropFrame
, 默认 就是开启的BaseDownloadTask#setSyncCallback
, 默认是false, 如果设置为true,所有的回调都会在下载线程直接同步调用而不会抛到ui线程。
FileDownloadMonitor
你可以添加一个全局监听器来进行打点或者是调试
FileDownloadMonitor.IMonitor
监听器接口类
pending
回调之前)onTaskStarted(task:BaseDownloadTask)将会在task结束pending开始task的runnable的时候回调该方法onTaskOver(task:BaseDownloadTask)将会在task走完所有生命周期是回调这个方法FileDownloadUtils
BaseDownloadTask#setPath
这个路径将会作为它的Root pathFileDownloadNotificationHelper
如何快速集成Notification呢? 建议参考NotificationDemoActivity
filedownloader.properties
如果你需要定制化FileDownloader,可以在你的项目模块的
assets
目录下添加 'filedownloader.properties' 文件(如/demo/src/main/assets/filedownloader.properties
),然后添加以下可选相关配置。格式:
keyword=value
true
即可,我们将会将其作为chunck
进行处理falseprocess.non-separateFileDownloadService 默认是运行在独立进程':filedownloader'上的, 如果你想要FileDownloadService共享并运行在主进程上, 将该关键字参数设置为true
,可以有效减少IPC产生的I/Ofalsedownload.min-progress-step最小缓冲大小,用于判定是否是时候将缓冲区中进度同步到数据库,以及是否是时候要确保下缓存区的数据都已经写文件。值越小,更新会越频繁,下载速度会越慢,但是应对进程被无法预料的情况杀死时会更加安全65536download.min-progress-time最小缓冲时间,用于判定是否是时候将缓冲区中进度同步到数据库,以及是否是时候要确保下缓存区的数据都已经写文件。值越小,更新会越频繁,下载速度会越慢,但是应对进程被无法预料的情况杀死时会更加安全2000download.max-network-thread-count用于同时下载的最大网络线程数, 区间[1, 12]3III. 异常处理
所有的异常,都将在
FileDownloadListener#error(BaseDownloadTask, Throwable)
中获知。
FileDownloadHttpException
在发出请求以后,response-code不是200(HTTP_OK),也不是206(HTTP_PARTIAL)的情况下会抛出该异常; 在这个异常对象会带上 response-code、response-header、request-header。FileDownloadGiveUpRetryException
在请求返回的 response-header 中没有带有文件大小(content-length),并且不是流媒体(transfer-encoding)的情况下会抛出该异常;出现这个异常,将会忽略所有重试的机会(BaseDownloadTask#setAutoRetryTimes
). 你可以通过在 filedownloader.properties
中添加 http.lenient=true
来忽略这个异常,并且在该情况下,直接作为流媒体进行下载。FileDownloadOutOfSpaceException
当将要下载的文件大小大于剩余磁盘大小时,会抛出这个异常。其他程序错误。III. 低内存情况
非下载进程(一般是UI进程):
这边的数据并不多,只是一些队列数据,用不了多少内存。
前台进程数据被回收:
如果在前台的时候这个数据都被回收了, 你的应用应该也挂了。极低概率事件。
后台进程数据被回收:
一般事件, 如果是你的下载是UI进程启动的,如果你的UI进程处于后台进程
(可以理解为应用被退到后台)状态,在内存不足的情况下会被回收(回收优先级高于服务进程
),此时分两种情况:
是串行队列任务,在回收掉UI进程内存以后,下载进程会继续下载完已经pending到下载进程的那个任务,而还未pending到下载进程的任务会中断下载(由于任务驱动线性执行的是在UI进程); 有损体验: 下次进入应用重启启动整个队列,会继续上次的下载。
是并行队列任务,在回收掉UI进程内存以后,下载进程会继续下载所有任务(所有已经pending到下载进程的任务,由于这里的pending速度是很快的,因此几乎是点击并行下载,所有任务在很短的时间内都已经pending到下载进程了),而UI进程由于被回收,将不会收到所有的监听; 有损体验: 下次进入应用重新启动整个队列,就会和正常的下载启动一致,收到所有情况的监听。
下载进程:
对内存有一定的占用,但是并不多,每次启动进程会根据数据的有效性进行清理冗余数据,被回收是低概率事件
由于下载不断有不同的buffer占用内存,但是由于在下载时,是活跃的服务进程
,因此被回收是低概率事件(会先回收完所有空进程
、后台进程
(后台应用)以后,如果内存还不够,才会回收该进程)。
即使被回收,也不会有任何问题。由于我们使用的是START_STICKY
(如果不希望被重启可主动调用FileDownloader#unBindService
/FileDownloader#unBindServiceIfIdle
),因此在内存足够的时候,下载进程会尝试重启(系统调度),非下载进程(一般是UI进程) 接收到下载进程的连接,会继续下载与继续接收回调,下载进程也会断点续传没有下载完的所有任务(无论并行与串行),不会影响体验。
- FileDownloader 库推荐
- Android高能下载库FileDownloader
- lingochamp/FileDownloader
- android FileDownloader
- filedownloader使用
- 使用FileDownLoader下载文件
- 使用FileDownLoader下载文件
- Android 文件下载引擎 FileDownloader
- FileDownloader-Android 文件下载引擎,稳定、高效、简单易用
- Android 文件下载引擎,稳定、高效、简单易用:FileDownloader
- 解决FileDownloader库中无全部开始下载任务接口的问题
- 库推荐
- Android 文件下载引擎,稳定、高效、简单易用:FileDownloader(结合okhttp)
- Android 文件下载引擎,稳定、高效、简单易用:FileDownloader(结合okhttp)
- 推荐一个算法库
- .net 导出库推荐
- 推荐两个C库
- Java库推荐-trove4j
- 使用LocalBroadcast实现跨Activity的MVVM
- 初试base64:神秘邮件
- 我读《把时间当做朋友》
- UVA10003 Cutting Sticks(区间 DP)
- C++中内置变量初始化及private继承相关
- FileDownloader 库推荐
- Centos下更新 gcc 版本至 GCC 6.1.0
- 不可变类
- win10下的 Genymoyion下的配置
- EXPLOITING CVE-2016-2060 ON QUALCOMM DEVICES
- WPF学习之数据绑定
- iOS获取各种文件目录路径的方法
- Understanding LSTM Networks
- HDOJ(HDU) 2317 Nasty Hacks(比较、)