系统自带的 API DownloadManager 用着太麻烦?来看看这个简单易用第三方库AwesomeDownloader

1,117 阅读2分钟

前言:

 DownloadManger是android 2.3(API 9)开始提供的系统服务,可处理长时间运行的HTTP下载。客户端可以请求将URI下载到特定的目标文件。下载管理器将在后台进行下载,负责HTTP交互,并在出现故障或在连接更改和系统重新启动后重试下载。 通过此API请求下载的应用应为ACTION_NOTIFICATION_CLICKED注册一个广播接收器,以便当用户在通知或下载UI中单击正在运行的下载时进行适当处理。

不过DownloadManger也有不足的地方如:

  1. 监听下载完成事件麻烦,需要注册特定的Broadcast。
  2. 监听下载进度麻烦,需要通过DownloadManager.Query获取游标不断查询。
  3. 需手动实现断点续传。

以下是用DownloadManger下载文件的一段代码:

val url = "https://images.gitee.com/uploads/images/2020/0914/131423_f1aaba0b_1899542.png"
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val request = DownloadManager.Request(Uri.parse(url))
request.setDestinationInExternalFilesDir( this , Environment.DIRECTORY_DOWNLOADS ,  "test.png" )
val downloadId = downloadManager.enqueue(request)

总而言之就是觉得代码不够干脆,使用起来太麻烦。

所以我写了一个基于Retrofit和kotlin协程实现的下载器AwesomeDownloader,用来代替它使用。(技术拙劣,轻喷o(╯□╰)o)

开始使用:

导入依赖:

在根目录build.gradle中,添加jitpack,io

allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}

添加依赖:

	dependencies {
	        implementation 'com.gitee.jiang_li_jie_j:awesome-downloader:v1.0.1'
	}

 这里查看版本 gitee.com/jiang_li_ji…  or 

github.com/AManCallJia…

使用:

  1. 使用前需要为您的APP申请读写权限,网络权限

  2. 调用init()初始化下载器,传入Application的context,以免内存泄露

    AwesomeDownloader.init(applicationContext)
    
  3. 下载文件 

    val url = "https://images.gitee.com/uploads/images/2020/0914/131423_f1aaba0b_1899542.png"
    //获取应用外部照片储存空间路径
    val filePath = PathSelector(applicationContext).getPicturesDirPath()
    val fileName = "test.png"
    //加入下载队列
    AwesomeDownloader.enqueue(url, filePath!!, fileName)
    
  4. 下载控制

           //停止全部
            AwesomeDownloader.stopAll()
            //恢复下载
            AwesomeDownloader.resumeAndStart()
            //取消当前
            AwesomeDownloader.cancel()
            //取消全部
            AwesomeDownloader.cancelAll()
    
  5. 设置监听

            AwesomeDownloader.setOnProgressChange { progress ->
                //do something...
            }.setOnStop { downloadBytes, totalBytes ->
                //do something...
            }.setOnFinished { filePath, fileName ->
                //do something...
            }.setOnError { exception ->
                //do something...
            }
    
  6. 设置自定义通知栏

(AwesomeDownloader默认显示的通知栏)

设置中确保showNotification为true

 AwesomeDownloader.option.showNotification = true

调用setNotificationSender()

override 抽象类NotificationSender 的三个方法

AwesomeDownloader.setNotificationSender(object : NotificationSender(applicationContext) {
                //创建显示任务下载进度的Notification
                override fun buildDownloadProgressNotification(
                    progress: Int,
                    fileName: String
                ): Notification {
                    return NotificationCompat.Builder(context, CHANNEL_ID)
                        .setSmallIcon(R.drawable.ic_baseline_adb_24)
                        .setContentTitle("$fileName 下载中")
                        .setContentText("$progress%")
                        .setPriority(NotificationCompat.PRIORITY_HIGH)
                        .build()
                }

                //创建显示任务下载停止的Notification
                override fun buildDownloadStopNotification(fileName: String): Notification {
                    return NotificationCompat.Builder(context, CHANNEL_ID)
                        .setSmallIcon(R.drawable.ic_baseline_adb_24)
                        .setContentTitle("$fileName Stop")
                        .setContentText("Stop")
                        .setPriority(NotificationCompat.PRIORITY_HIGH)
                        .build()
                }

                //创建显示任务下载完成的Notification
                override fun buildDownloadDoneNotification(
                    filePath: String,
                    fileName: String
                ): Notification {
                    Log.d(TAG, "buildDownloadDoneNotification: start")
                    return if (isImageFile(fileName)) {
                        val bitmap =
                            BitmapFactory.decodeFile("$filePath/$fileName")
                        Log.d(TAG, "buildDownloadDoneNotification: done")
                        NotificationCompat.Builder(context, CHANNEL_ID)
                            .setSmallIcon(R.drawable.ic_baseline_adb_24)
                            .setContentTitle("$fileName Done")
                            .setContentText("Done")
                            .setStyle(
                                NotificationCompat.BigPictureStyle()
                                    .bigPicture(bitmap)
                                    .bigLargeIcon(null)
                            )
                            .setPriority(NotificationCompat.PRIORITY_HIGH)
                            .build()

                    } else {
                        NotificationCompat.Builder(context, CHANNEL_ID)
                            .setSmallIcon(R.drawable.ic_baseline_adb_24)
                            .setContentTitle("$fileName Done")
                            .setContentText("Done")
                            .setPriority(NotificationCompat.PRIORITY_HIGH)
                            .build()
                    }
                }
            })

_(通知栏效果可能因为Android版本不同和手机厂商不同而效果不一致)_

7.查询下载任务

在协程中调用挂起函数查询

   lifecycleScope.launch (Dispatchers.IO){
                //查询所有任务信息
                AwesomeDownloader.queryAllTaskInfo().forEach {
                    Log.d(tag, "$it")
                }
                //查询未完成的任务信息
                AwesomeDownloader.queryUnfinishedTaskInfo().forEach {
                    Log.d(tag, "$it")
                }
                //查询已完成的任务信息
                AwesomeDownloader.queryFinishedTaskInfo().forEach {
                    Log.d(tag, "$it")
                }
            }

或者直接返回LiveData

           AwesomeDownloader.getAllTaskInfoLiveData().observe(
                this, Observer { list -> list.forEach { Log.d(tag, "$it") } })

           AwesomeDownloader.getUnfinishedTaskInfoLiveData().observe(
                this, Observer { list -> list.forEach { Log.d(tag, "$it") } })

           AwesomeDownloader.getFinishedTaskInfoLiveData().observe(
                this, Observer { list -> list.forEach { Log.d(tag, "$it") } })

AwesomeDownloader项目代码:

gitee.com/jiang_li_ji…   

or 

github.com/AManCallJia…