Android 经典笔记之五:DownloadManager下载管理器介绍

来源:互联网 发布:济南行知小学作文 编辑:程序博客网 时间:2024/06/05 12:46

0.简单介绍

  • 关于DownloadManager简单介绍 DownloadManager是android2.3以后,系统下载的方法,是处理长期运行的HTTP下载的系统服务。客户端可以请求的URI被下载到一个特定的目标文件。客户端将会在后台与http交互进行下载,或者在下载失败,或者连接改变,重新启动系统后重新下载。还可以进入系统的下载管理界面查看进度。DownloadManger有两个内部类,Request 和Query。Request类可设置下载的一些属性。Query类可查询当前下载的进度,下载地址,文件存放目录等数据。

1.所需权限

  1. <uses-permission android:name="android.permission.INTERNET" />;
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>;
  3. 注意,访问本地控件【sd卡,手机内存卡】需要检测是否添加权限
  4. /**检测存储权限*/
  5. private final int REQUEST_EXTERNAL_STORAGE = 1;
  6. private String[] PERMISSIONS_STORAGE = {
  7. Manifest.permission.READ_EXTERNAL_STORAGE,
  8. Manifest.permission.WRITE_EXTERNAL_STORAGE
  9. };
  10. public void verifyStoragePermissions(Activity activity) {
  11. // Check if we have write permission
  12. int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
  13. if (permission != PackageManager.PERMISSION_GRANTED) {
  14. // We don't have permission so prompt the user
  15. ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
  16. }
  17. }

2.获取对象,开始下载

  • 获取对象,开始下载
    1. DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
    2. DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
    3. long id = downloadManager.enqueue(request);
    4. //每下载的一个文件对应一个id,通过此id可以查询数据。

3.取消下载

  1. downloadManager.remove(REFERENCE_1, REFERENCE_2, REFERENCE_3);
  2. 该方法返回成功取消的下载的个数,如果一个下载被取消了,所有相关联的文件,部分下载的文件和完全下载的文件都会被删除.

4.Request类的介绍

  1. /**
  2. * 方法1:
  3. * 目录: Android -> data -> com.app -> files -> Download -> dxtj.apk
  4. * 这个文件是你的应用所专用的,软件卸载后,下载的文件将随着卸载全部被删除
  5. */
  6. request.setDestinationInExternalFilesDir( this , Environment.DIRECTORY_DOWNLOADS , "dxtj.apk" );
  1. /**
  2. * 方法2:
  3. * 下载的文件存放地址 SD卡 download文件夹,dxtj.apk
  4. * 软件卸载后,下载的文件会保留
  5. */
  6. //在SD卡上创建一个文件夹
  7. request.setDestinationInExternalPublicDir( "/epmyg/" , "dxtj.apk" ) ;
  1. /**
  2. * 方法3:
  3. * 如果下载的文件希望被其他的应用共享
  4. * 特别是那些你下载下来希望被Media Scanner扫描到的文件(比如音乐文件)
  5. */
  6. request.setDestinationInExternalPublicDir( Environment.DIRECTORY_MUSIC, "告白气球.mp3" );
  1. /**
  2. * 方法4【投资界和新芽目前用这个】
  3. * 文件将存放在外部存储的确实download文件内,如果无此文件夹,创建之,如果有,下面将返回false。
  4. * 系统有个下载文件夹,比如小米手机系统下载文件夹 SD卡--> Download文件夹
  5. */
  6. //创建目录
  7. Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ;
  8. //设置文件存放路径
  9. request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS , "dxtj.apk" ) ;
  • 4.1 指定下载的类型
    1. //指定在WIFI状态下,执行下载操作。
    2. request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
    3. //指定在MOBILE状态下,执行下载操作
    4. request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE);
    5. //是否允许漫游状态下,执行下载操作
    6. request.setAllowedOverRoaming(boolean);
    7. //是否允许“计量式的网络连接”执行下载操作
    8. request.setAllowedOverMetered(boolean); //默认是允许的。
  • 4.2 定制Notification样式
    1. //设置Notification的标题和描述
    2. request.setTitle("标题");
    3. request.setDescription("描述");
    4. //设置Notification的显示,和隐藏。
    5. request.setNotificationVisibility(visibility);
    6. VISIBILTY_HIDDEN: Notification:将不会显示,如果设置该属性的话,必须要添加权限
    7. android.permission.DOWNLOAD_WITHOUT_NOTIFICATION.
    8. VISIBILITY_VISIBLE Notification显示,但是只是在下载任务执行的过程中显示,下载完成自动消失。(默认值)
    9. VISIBILITY_VISIBLE_NOTIFY_COMPLETED : Notification显示,下载进行时,和完成之后都会显示。
    10. VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION :只有当任务完成时,Notification才会显示。
    11. Notification的设定方法相对较少。
  • 4.3 设置下载文件类型

    1. request.setMimeType("application/vnd.android.package-archive");
    2. 这是安卓.apk文件的类型。有些机型必须设置此方法,才能在下载完成后,点击通知栏的Notification时,才能正确的打开安装界面。不然会弹出一个Toastcan not open file).其他文件类型的MimeType
  • 4.4 添加请求下载的网络链接的http头,比如User-Agent,gzip压缩等
    1. request.addRequestHeader(String header, String value);

5.Query 类

  • 我们的需求,可能不只是在Notification 中显示进度就好了,也许,在app中也需要获取实时下载进度。所以Query类就是提供查询的一些方法。
  • 但API中就只有两个方法,原来,他把数据保存在数据库中去了。我们需要获得一个Cursor 结果集,通过结果集获得我们想要的数据。
    1. DownloadManager.Query query = new DownloadManager.Query();
    2. Cursor cursor = downloadManager.query(query.setFilterById(id));
    3. if (cursor != null && cursor.moveToFirst()) {
    4. //下载的文件到本地的目录
    5. String address = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
    6. //已经下载的字节数
    7. int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
    8. //总需下载的字节数
    9. int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
    10. //Notification 标题
    11. String title =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
    12. //描述
    13. String description =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION));
    14. //下载对应id
    15. long id =cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
    16. //下载文件名称
    17. String filename =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
    18. //下载文件的URL链接
    19. String url =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
    20. }

6.不足之处

  • 1、我发现,在下载的时候,发送Notification时 是没有声音的。也没有设置声音的方法。不过这影响不大。主要的功能实现就好。
  • 2、因为这是系统的类,每个系统的Notification界面是不一样的。这就是每个rom厂家的自定义了。小米和魅族的就大不一样。魅族Notification上有一个下载暂停的按钮,而小米没有。所以导致Notification是不能统一的。其实,暂停的话用户可以点击notification,进入到下载管理界面,就有暂停按钮了。

7.代码案例【简易】

  1. /**
  2. * 开始下载
  3. * @param context
  4. */
  5. private static void startDownload(Context context) {
  6. int status = getDownloadStatus(context);
  7. if (status != DOWNLOAD_STATUS_NEED_LOAD) {
  8. // 不用下载则无需下列操作
  9. return;
  10. }
  11. DialogUtils.showToast(context, "开始下载安装包...");
  12. // parse url
  13. Uri mUri = Uri.parse(path);
  14. // create request
  15. DownloadManager.Request r = new DownloadManager.Request(mUri);
  16. // set request property
  17. String apkName = getDownloadApkName(context);
  18. // set 下载路径
  19. r.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkName);
  20. // set Notification
  21. r.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
  22. // create manager
  23. DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
  24. // key code, set mine type
  25. r.setMimeType("application/vnd.android.package-archive");
  26. // add to queue
  27. dm.enqueue(r);
  28. }
  29. /**获得Apk的名称*/
  30. @NonNull
  31. private static String getDownloadApkName(Context context) {
  32. return context.getString(R.string.app_name) + "_" + version + ".apk";
  33. }
  34. /**
  35. * 判断当前版本文件下载状态
  36. * @param context
  37. * @return
  38. */
  39. private static int getDownloadStatus(Context context) {
  40. DownloadManager.Query query = new DownloadManager.Query();
  41. DownloadManager dm = (DownloadManager) context.getSystemService(Activity.DOWNLOAD_SERVICE);
  42. Cursor c = dm.query(query);
  43. if (!c.moveToFirst()) {
  44. // 无下载内容
  45. return DOWNLOAD_STATUS_NEED_LOAD;
  46. }
  47. do {
  48. int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
  49. String title = c.getString(c.getColumnIndex(DownloadManager.COLUMN_TITLE));
  50. String apkName = getDownloadApkName(context);
  51. if (title.equals(apkName)) {
  52. // 如果下载列表中文件是当前版本应用,则继续判断下载状态
  53. if (status == DownloadManager.STATUS_SUCCESSFUL) {
  54. // 如果已经下载,返回状态,同时直接提示安装
  55. String uri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
  56. promptInstall(context, Uri.parse(uri));
  57. return DOWNLOAD_STATUS_LOADED;
  58. } else if (status == DownloadManager.STATUS_RUNNING
  59. || status == DownloadManager.STATUS_PAUSED
  60. || status == DownloadManager.STATUS_PENDING) {
  61. return DOWNLOAD_STATUS_RUNNING;
  62. } else {
  63. // 失败也视为可以再次下载
  64. return DOWNLOAD_STATUS_NEED_LOAD;
  65. }
  66. }
  67. } while (c.moveToNext());
  68. return DOWNLOAD_STATUS_NEED_LOAD;
  69. }
  70. /**
  71. * 根据下载队列id获取下载Uri
  72. * @param enqueueId
  73. * @return null-获取不到
  74. */
  75. public static Uri getDownloadUriById(Context context, long enqueueId) {
  76. DownloadManager.Query query = new DownloadManager.Query();
  77. query.setFilterById(enqueueId);
  78. DownloadManager dm = (DownloadManager) context.getSystemService(Activity.DOWNLOAD_SERVICE);
  79. Cursor c = dm.query(query);
  80. if (c.moveToFirst()) {
  81. int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
  82. if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
  83. String uri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
  84. return Uri.parse(uri);
  85. }
  86. }
  87. return null;
  88. }
  89. /**
  90. * 安装文件
  91. * @param context 上下文
  92. * @param data uri地址
  93. */
  94. public static void promptInstall(Context context, Uri data) {
  95. Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(data, "application/vnd.android.package-archive");
  96. // FLAG_ACTIVITY_NEW_TASK 可以保证安装成功时可以正常打开 app
  97. promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  98. context.startActivity(promptInstall);
  99. }
阅读全文
0 0
原创粉丝点击