从Android 2.3(API level 9)开始Android用系统服务(Service)的方式提供了Download Manager来优化处理长时间的下载操作。Download Manager处理HTTP 连接并监控连接中的状态变化以及系统重启来确保每一个下载任务顺利完成。 在大多数涉及到下载的情况中使用Download Manager都是不错的选择,特别是当用户切换不同的应用以后下载需要在后台继续进行,以及当下载任务顺利完成非常重要的情况(DownloadManager对于断点续传功能支持很好)。

###一、DownloadManager简单介绍 DownloadManager是系统开放给第三方应用使用的类,包含两个静态内部类DownloadManager.Query和DownloadManager.Request。DownloadManager.Request用来请求一个下载,DownloadManager.Query用来查询下载信息,这两个类的具体功能会在后面穿插介绍。DownloadManager的源码可见DownloadManager@Grepcode。   DownloadManager主要提供了下面几个接口:**public long enqueue(Request request)**执行下载,返回downloadId,downloadId可用于后面查询下载信息。若网络不满足条件、Sdcard挂载中、超过最大并发数等异常会等待下载,正常则直接下载。**public int remove(long… ids)**删除下载,若下载中取消下载。会同时删除下载文件和记录。**public Cursor query(Query query)**查询下载信息。   public static Long getRecommendedMaxBytesOverMobile(Context context通过移动网络下载的最大字节数public String getMimeTypeForDownloadedFile(long id)得到下载的mimeType,如何设置后面会进行介绍   其它:通过查看代码我们可以发现还有个CursorTranslator私有静态内部类。这个类主要对Query做了一层代理。将DownloadProvider和DownloadManager之间做个映射。将DownloadProvider中的十几种状态对应到了DownloadManager中的五种状态,DownloadProvider中的失败、暂停原因转换为了DownloadManager的原因。 ###简单使用 完成一个下载任务只需要4行代码,什么断点续传,大文件下载,通知栏进度显示....都不需要你操心。

//创建下载任务,downloadUrl就是下载链接
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
//指定下载路径和下载文件名
request.setDestinationInExternalPublicDir("/download/", fileName);
//获取下载管理器
DownloadManager downloadManager= (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
//将下载任务加入下载队列,否则不会进行下载
downloadManager.enqueue(request);
复制代码

###高级用法 具体的使用方法

要想使用Download Manager,使用getSystemService方法请求系统的DOWNLOAD_SERVICE服务,代码片段如下

//创建下载任务 DownloadManager.Request request = new DownloadManager.Request(Uri.parse(versionUrl)); request.setAllowedOverRoaming(false);//漫游网络是否可以下载 //设置文件类型,可以在下载结束后自动打开该文件 MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); String mimeString = mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(versionUrl)); request.setMimeType(mimeString); //在通知栏中显示,默认就是显示的 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); request.setVisibleInDownloadsUi(true); //sdcard的目录下的download文件夹,必须设置 request.setDestinationInExternalPublicDir("/download/", versionName); //request.setDestinationInExternalFilesDir(),也可以自己制定下载路径 //将下载请求加入下载队列 downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE); //加入下载队列后会给该任务返回一个long型的id, //通过该id可以取消任务,重启任务等等,看上面源码中框起来的方法 mTaskId = downloadManager.enqueue(request);
复制代码

要请求一个下载操作,需要创建一个DownloadManager.Request对象,将要请求下载的文件的Uri传递给Download Manager的enqueue方法

String serviceString = Context.DOWNLOAD_SERVICE;
DownloadManager downloadManager;
downloadManager = (DownloadManager)getSystemService(serviceString);
Uri uri = Uri.parse("http://developer.android.com/shareables/icon_templates-v4.0.zip");
DownloadManager.Request request = new Request(uri);
long reference = downloadManager.enqueue(request);
复制代码
String serviceString = Context.DOWNLOAD_SERVICE;
DownloadManager downloadManager;
downloadManager = (DownloadManager)getSystemService(serviceString);  Uri uri = Uri.parse("http://developer.android.com/shareables/icon_templates-v4.0.zip");
DownloadManager.Request request = new Request(uri);
long reference = downloadManager.enqueue(request);
复制代码

在这里返回的reference变量是系统为当前的下载请求分配的一个唯一的ID,我们可以通过这个ID重新获得这个下载任务,进行一些自己想要进行的操作或者查询 下载的状态以及取消下载等等。

我们可以通过addRequestHeader方法为DownloadManager.Request对象request添加HTTP头,也可以通过setMimeType方法重写从服务器返回的mime type。 我们还可以指定在什么连接状态下执行下载操作。setAllowedNetworkTypes方法可以用来限定在WiFi还是手机网络下进行下载,setAllowedOverRoaming方法 可以用来阻止手机在漫游状态下下载。 下面的代码片段用于指定一个较大的文件只能在WiFi下进行下载:

request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
复制代码

Android API level 11 介绍了getRecommendedMaxBytesOverMobile类方法(静态方法),返回一个当前手机网络连接下的最大建议字节数,可以来判断下载 是否应该限定在WiFi条件下。 调用enqueue方法之后,只要数据连接可用并且Download Manager可用,下载就会开始。 要在下载完成的时候获得一个系统通知(notification),注册一个广播接受者来接收ACTION_DOWNLOAD_COMPLETE广播,这个广播会包含一个 EXTRA_DOWNLOAD_ID信息在intent中包含了已经完成的这个下载的ID,代码片段如下所示:

IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
BroadcastReceiver receiver = new BroadcastReceiver() {  @Override  public void onReceive(Context context, Intent intent) {  long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);  if (myDownloadReference == reference) {  }  }
};
registerReceiver(receiver, filter);
```
>使用Download Manager的openDownloadedFile方法可以打开一个已经下载完成的文件,返回一个ParcelFileDescriptor对象。我们可以通过Download Manager来
查询下载文件的保存地址,如果在下载时制定了路径和文件名,我们也可以直接操作文件。
我们可以为ACTION_NOTIFICATION_CLICKED action注册一个广播接受者,当用户从通知栏点击了一个下载项目或者从Downloads app点击可一个下载的项目的
时候,系统就会发出一个点击下载项的广播。
代码片段如下:```
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_NOTIFICATION_CLICKED);
BroadcastReceiver receiver = new BroadcastReceiver() {  @Override  public void onReceive(Context context, Intent intent) {  String extraID = DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS;  long[] references = intent.getLongArrayExtra(extraID);  for (long reference : references)  if (reference == myDownloadReference) {  // Do something with downloading file.  }  }
};
registerReceiver(receiver, filter);
```
####定制Download Manager Notifications的样式>默认情况下,通知栏中会显示被Download Manager管理的每一个download每一个Notification会显示当前的下载进度和文件的名字,如下图所示:
通过Download Manager可以为每一个download request定制Notification的样式,包括完全隐藏Notification。下面的代码片段显示了通过setTitle和setDescription
方法来定制显示在文件下载Notification中显示的文字。```
request.setTitle(“Earthquakes”);
request.setDescription(“Earthquake XML”);
```>setNotificationVisibility方法可以用来控制什么时候显示Notification,甚至是隐藏该request的Notification。有以下几个参数:
**Request.VISIBILITY_VISIBLE**:在下载进行的过程中,通知栏中会一直显示该下载的Notification,当下载完成时,该Notification会被移除,这是默认的参数值。
**Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED**:在下载过程中通知栏会一直显示该下载的Notification,在下载完成后该Notification会继续显示,直到用户点击该
Notification或者消除该Notification。
**Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION**:只有在下载完成后该Notification才会被显示。
**Request.VISIBILITY_HIDDEN**:不显示该下载请求的Notification。如果要使用这个参数,需要在应用的清单文件中加上DOWNLOAD_WITHOUT_NOTIFICATION权限。
指定下载保存地址
默认情况下,所有通过Download Manager下载的文件都保存在一个共享下载缓存中,使用系统生成的文件名每一个Request对象都可以制定一个下载
保存的地址,通常情况下,所有的下载文件都应该保存在外部存储中,所以我们需要在应用清单文件中加上WRITE_EXTERNAL_STORAGE权限:```
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>
```
>下面的代码片段是在外部存储中指定一个任意的保存位置的方法:```
request.setDestinationUri(Uri.fromFile(f));
```
> f是一个File对象。
如果下载的这个文件是你的应用所专用的,你可能会希望把这个文件放在你的应用在外部存储中的一个专有文件夹中。注意这个文件夹不提供访问控制,
所以其他的应用也可以访问这个文件夹。在这种情况下,如果你的应用卸载了,那么在这个文件夹也会被删除。
下面的代码片段是指定存储文件的路径是应用在外部存储中的专用文件夹的方法:```
request.setDestinationInExternalFilesDir(this,  Environment.DIRECTORY_DOWNLOADS, “Bugdroid.png”);
```>如果下载的文件希望被其他的应用共享,特别是那些你下载下来希望被Media Scanner扫描到的文件(比如音乐文件),那么你可以指定你的下载路径在
外部存储的公共文件夹之下,下面的代码片段是将文件存放到外部存储中的公共音乐文件夹的方法:```
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC,  "Android_Rock.mp3");
```
>在默认的情况下,通过Download Manager下载的文件是不能被Media Scanner扫描到的,进而这些下载的文件(音乐、视频等)就不会在Gallery和
Music Player这样的应用中看到。
为了让下载的音乐文件可以被其他应用扫描到,我们需要调用Request对象的allowScaningByMediaScanner方法。
如果我们希望下载的文件可以被系统的Downloads应用扫描到并管理,我们需要调用Request对象的setVisibleInDownloadsUi方法,传递参数true。
取消和删除下载
Download Manager的remove方法可以用来取消一个准备进行的下载,中止一个正在进行的下载,或者删除一个已经完成的下载。
remove方法接受若干个download 的ID作为参数,你可以设置一个或者几个你想要取消的下载的ID,如下代码段所示:```
downloadManager.remove(REFERENCE_1, REFERENCE_2, REFERENCE_3);
```>该方法返回成功取消的下载的个数,如果一个下载被取消了,所有相关联的文件,部分下载的文件和完全下载的文件都会被删除。
查询Download Manager
你可以通过查询Download Manager来获得下载任务的状态,进度,以及各种细节,通过query方法返回一个包含了下载任务细节的Cursor。
query方法传递一个DownloadManager.Query对象作为参数,通过DownloadManager.Query对象的setFilterById方法可以筛选我们希望查询的下
载任务的ID。也可以使用setFilterByStatus方法筛选我们希望查询的某一种状态的下载任务,传递的参数是DownloadManager.STATUS_*常量,可以指定
正在进行、暂停、失败、完成四种状态。
Download Manager包含了一系列COLUMN_*静态String常量,可以用来查询Cursor中的结果列索引。我们可以查询到下载任务的各种细节,包括状态,
文件大小,已经下载的字节数,标题,描述,URI,本地文件名和URI,媒体类型以及Media Provider download URI。
下面的代码段是通过注册监听下载完成事件的广播接受者来查询下载完成文件的本地文件名和URI的实现方法:```
@Override
public void onReceive(Context context, Intent intent) {  long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);  if (myDownloadReference == reference) {  Query myDownloadQuery = new Query();  myDownloadQuery.setFilterById(reference);  Cursor myDownload = downloadManager.query(myDownloadQuery);  if (myDownload.moveToFirst()) {  int fileNameIdx =   myDownload.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);  int fileUriIdx =   myDownload.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);  String fileName = myDownload.getString(fileNameIdx);  String fileUri = myDownload.getString(fileUriIdx);  // TODO Do something with the file.  Log.d(TAG, fileName + " : " + fileUri);  }  myDownload.close();  }
}
```>对于暂停和失败的下载,我们可以通过查询COLUMN_REASON列查询出原因的整数码。
对于STATUS_PAUSED状态的下载,可以通过DownloadManager.PAUSED_*静态常量来翻译出原因的整数码,进而判断出下载是由于等待网络连接
还是等待WiFi连接还是准备重新下载三种原因而暂停。
对于STATUS_FAILED状态的下载,我们可以通过DownloadManager.ERROR_*来判断失败的原因,可能是错误码(失败原因)包括没有存储设备,
存储空间不足,重复的文件名,或者HTTP errors。
下面的代码是如何查询出当前所有的暂停的下载任务,提取出暂停的原因以及文件名称,下载标题以及当前进度的实现方法:```
// Obtain the Download Manager Service.
String serviceString = Context.DOWNLOAD_SERVICE;
DownloadManager downloadManager;
downloadManager = (DownloadManager)getSystemService(serviceString);  // Create a query for paused downloads.
Query pausedDownloadQuery = new Query();
pausedDownloadQuery.setFilterByStatus(DownloadManager.STATUS_PAUSED);  // Query the Download Manager for paused downloads.
Cursor pausedDownloads = downloadManager.query(pausedDownloadQuery);  // Find the column indexes for the data we require.
int reasonIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_REASON);
int titleIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TITLE);
int fileSizeIdx =   pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
int bytesDLIdx =   pausedDownloads.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);  // Iterate over the result Cursor.
while (pausedDownloads.moveToNext()) {  // Extract the data we require from the Cursor.  String title = pausedDownloads.getString(titleIdx);  int fileSize = pausedDownloads.getInt(fileSizeIdx);  int bytesDL = pausedDownloads.getInt(bytesDLIdx);  // Translate the pause reason to friendly text.  int reason = pausedDownloads.getInt(reasonIdx);  String reasonString = "Unknown";  switch (reason) {  case DownloadManager.PAUSED_QUEUED_FOR_WIFI :   reasonString = "Waiting for WiFi"; break;  case DownloadManager.PAUSED_WAITING_FOR_NETWORK :   reasonString = "Waiting for connectivity"; break;  case DownloadManager.PAUSED_WAITING_TO_RETRY :  reasonString = "Waiting to retry"; break;  default : break;  }  // Construct a status summary  StringBuilder sb = new StringBuilder();  sb.append(title).append("\n");  sb.append(reasonString).append("\n");  sb.append("Downloaded ").append(bytesDL).append(" / " ).append(fileSize);  // Display the status   Log.d("DOWNLOAD", sb.toString());
}  // Close the result Cursor.
pausedDownloads.close();
```
####参考
>[Android系统下载管理DownloadManager功能介绍及使用示例](http://www.trinea.cn/android/android-downloadmanager/)
[Android DownloadManager 的使用](http://blog.csdn.net/carrey1989/article/details/8060155)
[Android快速实现文件下载(只有4行代码)](http://www.jianshu.com/p/46fd1c253701)
复制代码

转载于:https://juejin.im/post/5a311488f265da431523e89d

ANDROID 系统下载相关推荐

  1. [Android]之一:Android系统下载管理DownloadManager

    嗷,这个android系统下载管理DownloadManager功能还是蛮强大的.虽然老大只是让我做一个下载工具类给他们使用,但是想加深一下印象,接下来是摘抄笔记,以后也要自己再看看不要又忘了. 一. ...

  2. Android系统下载管理DownloadManager

    转载: http://www.trinea.cn/android/android-downloadmanager/ http://www.trinea.cn/android/android-downl ...

  3. 小米笔记本安装android系统下载失败,小米平板电脑2如果刷成安卓的系统失败了怎么处理...

    把小米平板2刷成WIN10系统的方法: 一.更新BIOS版本 为了更好的使用win10系统,需要更新对应的bios版本,刷入过渡的android版本可更新并统一bios版本. 前提:已经安装mifla ...

  4. pc android系统下载,在PC上运行Android-x86 9.0-r1进行下载

    如果我在计算机上运行Android会怎样?以前,有许多双系统平板电脑可以在Windows和Android之间切换,但不再可见. 在x86电脑上安装Android有什么经验?通常,Android系统不能 ...

  5. Android系统下载管理DownloadManager功能介绍及使用示例

    一.DownloadManager简单介绍 DownloadManager是系统开放给第三方应用使用的类,包含两个静态内部类DownloadManager.Query和DownloadManager. ...

  6. Android 系统下载 DownloadManager

     一.所需权限 <uses-permission android:name="android.permission.INTERNET" /> <!--如果下载的文 ...

  7. 最新android系统下载,安卓6.0抢先体验方法|安卓6.0下载 安卓6.0系统下载地址_PC6教学...

    谷歌正式确定了Android M版本号为安卓6.0,同时确定其代号为MARshmallow(棉花糖),而且官方也放出了最新棉花糖系统的第三个开发者预览版固件,对于喜欢尝鲜和折腾用户肯定都想要升级体验一 ...

  8. ios 原生android系统下载地址,Android/iOS已有原生项目集成ReactNative

    背景 近期由于项目需要,在已经开发了几个版本的原生App中集成了ReactNative,新版的模块都使用RN开发. 此次集成的工作大部分是参照RN中文文档进行的,但是中文文档也有一些坑和描述不充分的地 ...

  9. 备份电视盒android系统下载,【当贝市场】教你如何提取、备份安卓电视盒子预装...

    原标题:[当贝市场]教你如何提取.备份安卓电视盒子预装 最新一键提取安卓电视.机顶盒自带软件方法! 至于为什么要提取系统自带软件,备份这些软件,请看此文,有非常详细的科普: 接下来,怎么样安全的删除. ...

最新文章

  1. RDKit:基于支持向量回归预测logP
  2. 使用 CommandBuilder 生成命令 (ADO.NET)
  3. es的forcemerge——按照天分割
  4. Unix哲学,Microservices和DDD (2)
  5. nodejs+express+mongodb简单的例子
  6. 2058. 找出临界点之间的最小和最大距离
  7. 办公自动化-演练-统计日报的演练-0223
  8. #define c# 报错_#define 预处理指令(C++,C#,VB.NET)
  9. 基于 MVP+RxJava2+Retrofit2 的应用—熊猫眼
  10. PADS2007快捷键、无模命令大全
  11. 小米笔记本linux系统下载,传小米笔记本不用Win10用Linux系统 推12.5寸/13.3寸两款...
  12. 什么是HTTP代理?
  13. 3705-26-8,cyclo(Phe-Pro),CYCLO-L-PHENYLALANYL-L-PROLINE,Einecs 223-047-0
  14. RFLA: Gaussian Receptive Field based Label Assignment for Tiny Object Detection
  15. 1.一个整形数组的最大值
  16. 初创企业融资PPT模板
  17. Centos7 内存插槽信息
  18. 电脑启动时显示windows无法正常启动怎么解决
  19. linux下卸载软件命令行,如何使用Linux中的命令行卸载软件 | MOS86
  20. tib_tiqu_without_temperature

热门文章

  1. [科普]DLL是什么
  2. 编译的时候所使用的动态库中出现错误:未定义的引用
  3. 24/09/2022 c语言细节
  4. OSChina 周三乱弹 —— 有舍才有得
  5. 计算机组成原理中J1J3是什么,计算机组成原理第一次实验报告.doc
  6. VCC VDD VSS
  7. HTML5+CSS3原百度浏览器背景奔跑的北极熊,加了点小玩意
  8. java学习顺序(学习路线图)
  9. ror 和 shr_使用RoR和React Native的ANPR
  10. 听说你立志要做数据分析,不如先听听老司机的建议?