DownloadManager

来源:互联网 发布:java双色球机选代码 编辑:程序博客网 时间:2024/05/21 22:55

本文链接: http://blog.csdn.net/xietansheng/article/details/52513624

在 Android 程序开发中如果需要下载文件,除了自己程序内部实现下载外,还可以直接使用 Android 系统自带的下载器进行下载,使用系统下载器通常有两种方式:

1. 浏览器下载

将下载链接使用浏览器打开,把下载任务交给浏览器,让浏览器调用系统下载器去下载,下载过程在通知栏有下载进度,下载完后文件通常存放在 “外部存储器” 根目录下的 download 文件夹, 也就是: /mnt/sdcard/download

打开下载链接的 Intent:

Intent intent = new Intent();intent.setAction(Intent.ACTION_VIEW);intent.addCategory(Intent.CATEGORY_BROWSABLE);intent.setData(Uri.parse("下载链接"));startActivity(intent);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

使用这种方法下载完全把工作交给了系统应用,自己的应用中不需要申请任何权限,方便简单快捷。但如此我们也不能知道下载文件的大小,不能监听下载进度和下载结果。

2. DownloadManager 系统服务

Android 2.3 (API 10) 以后,系统开放了内置下载器服务,也就是 DownloadManager,是专用于处理耗时长的 HTTP 文件下载的系统服务,在后台进行下载,并自动处理网络连接变化,失败重试。

通过 DownloadManager 我们可以在自己的程序中提交下载请求,在通知栏中可以自动显示下载进度展示通知进度条,可以指定下载文件的保存位置,并实时获取下载进度,监听下载结果。

DownloadManager 的实例通过 context.getSystemService(Context.DOWNLOAD_SERVICE) 获取,使用 DownloadManager 还必须要声明网络权限:android.permission.INTERNET;如果下载文件保存到外部存储器,还需要声明外部存储器的读写权限。

DownloadManager 中有两个重要的内部类:

  • 1) DownloadManager.Request :封装一个下载请求添加到系统下载器队列。
  • 2) DownloadManager.Query :查询下载任务,可实时获取下载进度,下载结果。

使用步骤:

1、配置权限

在 AndroidManifest.xml 配置权限:

<!-- 必须配置网络权限 --><uses-permission android:name="android.permission.INTERNET"/><!-- 如果将下载的文件保存到外部存储器,还需要配置外部存储器的读写权限 --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

2、封装下载请求(Request),加入下载队列

/* * 1. 封装下载请求 */// http 下载链接(该链接为 CSDN APP 的下载链接,仅做参考)String downloadUrl = "http://apk.hiapk.com/appdown/net.csdn.csdnplus";// 创建下载请求DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));/* * 设置在通知栏是否显示下载通知(下载进度), 有 3 个值可选: *    VISIBILITY_VISIBLE:                   下载过程中可见, 下载完后自动消失 (默认) *    VISIBILITY_VISIBLE_NOTIFY_COMPLETED:  下载过程中和下载完成后均可见 *    VISIBILITY_HIDDEN:                    始终不显示通知 */request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);// 设置通知的标题和描述request.setTitle("通知标题XXX");request.setDescription("对于该请求文件的描述");/* * 设置允许使用的网络类型, 可选值: *     NETWORK_MOBILE:      移动网络 *     NETWORK_WIFI:        WIFI网络 *     NETWORK_BLUETOOTH:   蓝牙网络 * 默认为所有网络都允许 */// request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);// 添加请求头// request.addRequestHeader("User-Agent", "Chrome Mozilla/5.0");// 设置下载文件的保存位置File saveFile = new File(Environment.getExternalStorageDirectory(), "demo.apk");request.setDestinationUri(Uri.fromFile(saveFile));/* * 2. 获取下载管理器服务的实例, 添加下载任务 */DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);// 将下载请求加入下载队列, 返回一个下载IDlong downloadId = manager.enqueue(request);// 如果中途想取消下载, 可以调用remove方法, 根据返回的下载ID取消下载, 取消下载后下载保存的文件将被删除// manager.remove(downloadId);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

3、查询下载状态(Query)

添加一个下载请求(Request)到下载管理器的队列中,将返回一个下载ID,通过该ID可以实时查询到下载进度,成功与失败等状态。

// 获取下载管理器服务的实例DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);// 创建一个查询对象DownloadManager.Query query = new DownloadManager.Query();// 根据 下载ID 过滤结果query.setFilterById(downloadId);// 还可以根据状态过滤结果// query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);// 执行查询, 返回一个 Cursor (相当于查询数据库)Cursor cursor = manager.query(query);if (!cursor.moveToFirst()) {    cursor.close();    return;}// 下载IDlong id = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));// 下载请求的状态int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));// 下载文件在本地保存的路径String localFilename = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));// 已下载的字节大小long downloadedSoFar = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));// 下载文件的总字节大小long totalSize = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));cursor.close();System.out.println("下载进度: " + downloadedSoFar  + "/" + totalSize);/* * 判断是否下载成功,其中状态 status 的值有 5 种: *     DownloadManager.STATUS_SUCCESSFUL:   下载成功 *     DownloadManager.STATUS_FAILED:       下载失败 *     DownloadManager.STATUS_PENDING:      等待下载 *     DownloadManager.STATUS_RUNNING:      正在下载 *     DownloadManager.STATUS_PAUSED:       下载暂停 */if (status == DownloadManager.STATUS_SUCCESSFUL) {    /*     * 特别注意: 查询获取到的 localFilename 才是下载文件真正的保存路径,在创建     * 请求时设置的保存路径不一定是最终的保存路径,因为当设置的路径已是存在的文件时,     * 下载器会自动重命名保存路径,例如: .../demo-1.apk, .../demo-2.apk     */    System.out.println("下载成功, 打开文件, 文件路径: " + localFilename);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

通常如果在自己的应用中需要显示下载进度,可以使用一个定时器,每隔1秒获取一次下载进度,然后根据自己的需求显示在界面上。

4、监听 点击通知 与 下载完成 的广播

上面查询下载状态的方式是自己主动轮询,监听下载完成更好的方式是监听系统下载服务发出的广播,DownloadManager 在用户点击了下载进度的通知栏 和 下载完成后 都会发出相应的广播。

广播实现:

package com.xiets.demo;import android.app.DownloadManager;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import java.util.Arrays;public class DownloadManagerReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        String action = intent.getAction();        if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {            System.out.println("用户点击了通知");            // 点击下载进度通知时, 对应的下载ID以数组的方式传递            long[] ids = intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);            System.out.println("ids: " + Arrays.toString(ids));        } else if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {            System.out.println("下载完成");            /*             * 获取下载完成对应的下载ID, 这里下载完成指的不是下载成功, 下载失败也算是下载完成,             * 所以接收到下载完成广播后, 还需要根据 id 手动查询对应下载请求的成功与失败.             */            long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L);            System.out.println("id: " + id);            // 根据获取到的ID,使用上面第3步的方法查询是否下载成功        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

在 AndroidManifest.xml 配置广播:

<receiver android:name="com.xiets.demo.DownloadManagerReceiver">    <intent-filter>        <!-- 配置 点击通知 和 下载完成 两个 action -->        <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>        <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>    </intent-filter></receiver>


0 0
原创粉丝点击