详解DownloadManager

一、概述

DownloadManager是处理长时间HTTP下载的系统服务。客户端可以将指定内容下载到某一特定的目录。DownloadManager会在后台进行下载工作,自己会处理下载失败、网络变换或系统重启等问题。可以通过下面的方法获取到DownloadManager对象,代码如下:

 DownloadManager mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
       
       
  • 1

一般使用DownloadManager时,应用需要注册一个可以接受ACTION_NOTIFICATION_CLICKED的广播接收器,用于恰当处理用户点击通知栏中的下载界面时的情形。另外,当使用DownloadManager时应用需要应具有INTERNET权限。

二、如何使用DownloadManager进行下载操作

DownloadManager一般用于软件更新、视频等的的下载任务,在通知栏中可以看到一个下载进度条,这种情形一般都是通过DownloadManager实现的。使用步骤由如下几步:

2.1、初始化DownloadManager.Request对象

DownloadManager.Request类包含了一个下载请求的所有必要信息。构造方法中只需要传入下载的URI,默认的文件存储地址是一个共享卷,当系统需要回收空间时可以能会删除下载文件。如果需要避免这种情况,可以使用setDestinationUrl(Uri)设置外部存储路径。 
Request可以设置限制使用的网络,默认是移动网络和WIFI网络均可以,如果想只设置WIFI网络,可以使用setAllowedNetWorkTypes进行设置,代码如下:

        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);

       
       
  • 1
  • 2

Request可以设置是否将下载进度显示在通知栏中,可以通过setNotificationVisibility(int visibility)进行设置。默认的,只会在下载进行中时显示,在下载完成后就不显示了。可以设置如下三个值: 
VISIBILITY_HIDDEN 下载UI不会显示,也不会显示在通知中,如果设置该值,需要声明android.permission.DOWNLOAD_WITHOUT_NOTIFICATION 
VISIBILITY_VISIBLE 当处于下载中状态时,可以在通知栏中显示;当下载完成后,通知栏中不显示 
VISIBILITY_VISIBLE_NOTIFY_COMPLETED 当处于下载中状态和下载完成时状态,均在通知栏中显示 
VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION 只在下载完成时显示在通知栏中。 
Request还有一些设置HTTP请求的方法,比如添加请求头addRequestHeader、设置MIME类型setMimeType等方法。 
下面是一段创建Request的示例代码:

 DownloadManager.Request request = new DownloadManager.Request(Uri.parse(PIC_URL));
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        request.setTitle("下载图片...");
       
       
  • 1
  • 2
  • 3
  • 4

上面的代码中根据下载的URL转成URI之后再创建Request对象,然后设置只允许使用WIFI网络,当任务在下载中时会在通知栏中显示进度,setTitle是设置通知的标题。

2.2、发送Request对象

当创建好Request对象后,只需要调用DownloadManager的enqueue(DownloadRequest request)方法将请求放入队列中,然后只要DownloadManager准备好执行该任务时就会自动执行,用户就不需要关心下载过程了。enqueue对象返回一个唯一的id号,以后就可以通过这个id与该下载请求关联进行查询等操作。调用enqueue对象如下所示:

 id = mDownloadManager.enqueue(request);
       
       
  • 1

当提交之后,运行效果如下: 
下载示例

2.3、创建Query对象查询下载进度

当需要查询下载进度或状态时,可以创建DownloadManager.Query对象,然后再调用DownloadManager.query方法进行查询,该方法返回一个Cursor对象,具体需要查询哪个字段可以查看DownloadManager的以COLUM_**开头的常量。创建Query对象后,可以根据id或者下载状态设置过滤条件。下面是一个查询示例:

DownloadManager.Query query = new DownloadManager.Query().setFilterById(id);
        Cursor cursor = mDownloadManager.query(query);

        if (cursor != null) {

            while (cursor.moveToNext()) {

                String bytesDownload = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                String descrition = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION));
                String id = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
                String localUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                String mimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
                String title = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
                String status = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                String totalSize = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));

                Log.i("MainActivity", "bytesDownload:" + bytesDownload);
                Log.i("MainActivity", "descrition:" + descrition);
                Log.i("MainActivity", "id:" + id);
                Log.i("MainActivity", "localUri:" + localUri);
                Log.i("MainActivity", "mimeType:" + mimeType);
                Log.i("MainActivity", "title:" + title);
                Log.i("MainActivity", "status:" + status);
                Log.i("MainActivity", "totalSize:" + totalSize);

            }

        }
       
       
  • 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

上面的代码是根据id设置的过滤条件,查询了一些字段,然后将其打到Log上,结果如下:

I/MainActivity: bytesDownload:290037
I/MainActivity: descrition:
I/MainActivity: id:137
I/MainActivity: localUri:content://downloads/my_downloads/137
I/MainActivity: mimeType:image/jpeg
I/MainActivity: title:下载图片...
I/MainActivity: status:200
I/MainActivity: totalSize:290037
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.4、取消下载任务

如果下载任务进行了一半之后,用户想取消该如何实现呢?可以通过DownloadManager的remove方法,传入enqueue返回的id即可。

2.5、注册广播监听通知栏点击事件和下载完成事件

当点击通知栏中的下载栏时,系统会发出ACTION_NOTIFICATION_CLICKED事件的广播,当下载完成时,系统会发出ACTION_DOWNLOAD_COMPLETE事件的广播,可以通过实现接受这样ACTION的广播处理一些事情。比如应用本来是后台下载,但是点击该按钮后,就弹出正在下载的对话框;应用下载好后,可以直接执行安装操作。下面的代码展示了如何实现这样的一个广播接收器:

/**
     * 广播接收器,接受ACTION_DOWNLOAD_COMPLETE和ACTION_NOTICATION_CLICKED
     */
    class DownloadReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {

                Uri uri = mDownloadManager.getUriForDownloadedFile(id);

                imageView.setImageURI(uri);

            } else if (intent.getAction().equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {

                Toast.makeText(context, "Clicked", Toast.LENGTH_SHORT).show();

            }

        }
    }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在上面的代码中,对于ACTION_NOTIFICATION_CLICKED广播,仅仅是显示Toast提示,当然可以在这儿做一些更复杂的操作;对于ACTION_DOWNLOAD_COMPLETE广播,因为上面下载的图片,所以完成后就直接给ImageView设置了。接下来就是需要注册广播接收器和在Activity销毁的时候解除广播接收器。 
结果如下图: 
下载示例

三、总结

DownloadManager的好处在于: 
1)后台执行网络操作,开发者无需关注网络切换、存储文件失败等问题 
2)在通知栏中显示下载进度,不需要开发者自己实现通知栏中的下载进度条 
3)可以很方便地进行查询和删除任务的功能 
代码移步我的Github



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值