DownloadManager分析(2)
昨天说到:
- DownloadManager分发任务给DownloadProvider
- DownloadProvider调用DownloadService
- DownloadService真正执行下载操作
所以DownloadProvider做了什么,怎么启动DownloadService的?然后DownloadSerivce又是怎么实现下载的?
DownloadProvider做了什么
DownloadProvider的描述是:
Allows application to interact with the download manager.
允许应用和download manager之间进行交互。
Application可以是不同的Application,DownloadProvider
继承了ContentProvider
,所以可以实现数据共享,事实上我们会发现下载到的内容都会被显示在「下载」这个原生APP里面,当然显示与否在DownloadManager里面是可以打开/关闭的。
前面分析到,Android N之前,DownloadManager
会把request以ContentValues
形式pass给DownloadProvider.insert()
,然后进行异步下载。
//传递URI和Content Values给ContentResolver
Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values);
DownloadProvider的insert方法,将下载信息写入数据库,包括下载链接地址等信息,然后会启动DownloadService
这个Service:
//连请求头都写入了数据库
insertRequestHeaders(db, rowID, values);
//启动DownloadService
context.startService(new Intent(context, DownloadService.class));
notifyContentChanged(uri, match);
return ContentUris.withAppendedId(Downloads.CONTENT_URI, rowID);
DownloadService做了什么
UpdateThread
DownloadService
会利用updateFromProvider
从provider的数据库里获取下载的请求,然后启动UpdateThread
线程,这个线程会不断地查找数据库里还有没有下载任务,以及还有没有未完成的任务,直到完成才退出。
//UpdateThread的run方法
for (;;) {
synchronized (DownloadService.this) {
if (mUpdateThread != this) {
throw new IllegalStateException(
"multiple UpdateThreads in DownloadService");
}
if (!mPendingUpdate) {
mUpdateThread = null;
if (!keepService) {
stopSelf();
}
if (wakeUp != Long.MAX_VALUE) {
scheduleAlarm(wakeUp);
}
return;
}
mPendingUpdate = false;
}
...
...
}
DownloadThread
DownloadThread
真正实现了下载,里面有很多功能,比如开始、暂停、断点续传。每个下载任务都是独立的线程,需要同步锁/线程池来限制下载数量。
有这些方法:
- excuteDownload 执行下载
- setupDestinationFile 设置目标位置,如果位置已经有了file,就继续下载,实现了断点续传
- addRequestHeaders 添加请求头
- checkConnectivity 检查链接
- readFromResponse 读取response
- writeDataToDestination 写数据
- reportProgress 报告进度
- checkPauseOrCanceled 检查暂停或取消
- cleanUpDestination 清空目标位置
- notifyDownloadComplete 通知下载完成(更新数据库/发送广播)
5~8是一个loop,不停地获取网络数据流,检查下载是否暂停。
关键的下载操作都是在DownloadThread
里面实现的,如果想参考就来这里看吧。另外,Android N之后DownloadProvider
引入了Job Schedule
,会将任务加入计划,满足指定条件再执行操作,App不用驻留,可以省电,大概是这样子。
总结一下:
graph LR
DownloadManager-->DownloadProvider
DownloadProvider-->DownloadService
DownloadService-->UpdateThread
DownloadService-->DownloadThread
UpdateThread-->DownloadProvider
-Dec30
Reference:
[1]http://www.jianshu.com/p/c9dc04af2f54#
[2]http://blog.csdn.net/zhiyi2010/article/details/19152979
[3]http://blog.csdn.net/qq_31726827/article/details/50462025