前言:
DownloadManger是android 2.3(API 9)开始提供的系统服务,可处理长时间运行的HTTP下载。客户端可以请求将URI下载到特定的目标文件。下载管理器将在后台进行下载,负责HTTP交互,并在出现故障或在连接更改和系统重新启动后重试下载。 通过此API请求下载的应用应为ACTION_NOTIFICATION_CLICKED注册一个广播接收器,以便当用户在通知或下载UI中单击正在运行的下载时进行适当处理。
不过DownloadManger也有不足的地方如:
- 监听下载完成事件麻烦,需要注册特定的Broadcast。
- 监听下载进度麻烦,需要通过DownloadManager.Query获取游标不断查询。
- 需手动实现断点续传。
以下是用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
使用:
-
使用前需要为您的APP申请读写权限,网络权限
-
调用init()初始化下载器,传入Application的context,以免内存泄露
AwesomeDownloader.init(applicationContext)
-
下载文件
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)
-
下载控制
//停止全部 AwesomeDownloader.stopAll() //恢复下载 AwesomeDownloader.resumeAndStart() //取消当前 AwesomeDownloader.cancel() //取消全部 AwesomeDownloader.cancelAll()
-
设置监听
AwesomeDownloader.setOnProgressChange { progress -> //do something... }.setOnStop { downloadBytes, totalBytes -> //do something... }.setOnFinished { filePath, fileName -> //do something... }.setOnError { exception -> //do something... }
-
设置自定义通知栏
(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项目代码:
or