下載器封裝,便于開發(fā)跷坝,使用downloadManager〉锏铮可以監(jiān)聽下載進(jìn)度柴钻,監(jiān)聽方法里使用了協(xié)程,也可以使用線程進(jìn)行監(jiān)聽垢粮,同時(shí)使用contentProvider來(lái)獲取全局上下文贴届,所以在使用中無(wú)需傳遞上下文。
此文僅用于本人記錄開發(fā)經(jīng)驗(yàn)所用蜡吧。
```
/**
*@Company NSNTC
*@author Chord.p
*@time 2020/3/20 9:44 AM
*speak softly love
*
* 下載器毫蚓,暫時(shí)無(wú)法管理多下載任務(wù)狀態(tài)
*/
class DownloadHelper {
//下載器
? ? private var downloadManager : DownloadManager = DownloadProvider.mContext.getSystemService(Context.DOWNLOAD_SERVICE)as DownloadManager
//下載時(shí)相關(guān)配置
? ? private var options = DownloadOptions()
//下載開始監(jiān)聽器,回調(diào)參數(shù)為下載id斩跌,可通過(guò)該id對(duì)該下載任務(wù)進(jìn)行管理
? ? var preparListener : DownloadBaseListener? =null
? ? //下載中監(jiān)聽器绍些,回調(diào)參數(shù)為下載進(jìn)度,范圍在0~100
? ? var downloadingListener : DownloadBaseListener? =null
? ? //下載失敗監(jiān)聽器
? ? var downloadFailListener : DownloadNoteListener? =null
? ? //下載延遲監(jiān)聽器
? ? var downloadPenddingListener : DownloadNoteListener? =null
? ? //下載暫停監(jiān)聽器
? ? var downloadPauseListener : DownloadNoteListener? =null
? ? //下載成功監(jiān)聽器耀鸦,回調(diào)參數(shù)為本地存儲(chǔ)路徑
? ? var downloadSuccessListener : DownloadBaseListener? =null
? ? //下載周期監(jiān)聽器
? ? var downloadListener : DownloadListener? =null
? ? //下載id
? ? var id =0L
? ? //下載地址
? ? var path =""
? ? companion object {
val instance : DownloadHelperby lazy(::DownloadHelper)
fun apkDownload(url : String,name : String,deleteIfExists : Boolean =true) {
instance.downloadApk(url, name, deleteIfExists)
}
fun downloadFile(url : String,name : String,deleteIfExists : Boolean =true) {
instance.download(url, name, deleteIfExists)
}
/**
* 請(qǐng)使用DownloadOptions下的常量進(jìn)行設(shè)定
*/
? ? ? ? fun setNetType(type : String) {
instance.options.netType = type
}
fun setDownloadPath(path : String) {
instance.options.downloadPath = File(path)
}
fun setDownloadPath(path : File) {
instance.options.downloadPath = path
}
/**
* 請(qǐng)使用DownloadManager.Request 下的常量進(jìn)行設(shè)定
*/
? ? ? ? fun setShowNotify(showType : Int) {
instance.options.showNotify = showType
}
fun setDownloadListener(listener : DownloadListener) {
instance.downloadListener = listener
}
fun setPrepardListener(listener: DownloadBaseListener) {
instance.preparListener = listener
}
fun setNotifyTitle(title: String) {
instance.options.title = title
}
fun setNotifyDesc(desc : String) {
instance.options.desc = desc
}
}
fun downloadApk(url : String,name : String,deleteIfExists : Boolean =true) {
var request = DownloadManager.Request(Uri.parse(url))
request.setAllowedOverRoaming(false)
when(options.netType) {
DOWNLOAD_ONLY_PHONE -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE)
DOWNLOAD_ONLY_WIFI -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)
DOWNLOAD_NO_CARE -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
}
//設(shè)置是否顯示通知欄
? ? ? ? request.setNotificationVisibility(options.showNotify)
//設(shè)置通知欄標(biāo)題
? ? ? ? request.setTitle(options.title)
//設(shè)置通知欄簡(jiǎn)介
? ? ? ? request.setDescription(options.desc)
request.setVisibleInDownloadsUi(true)
//指定下載的文件類型為APK
? ? ? ? request.setMimeType("application/vnd.android.package-archive")
var file = File(options.downloadPath,name)
//若已存在該文件柬批,則刪除
? ? ? ? if (file.exists()) {
if (deleteIfExists) {
file.delete()
}else{
Log.e("download","file is exists")
return
? ? ? ? ? ? }
}
request.setDestinationUri(Uri.fromFile(file))
path = file.absolutePath
? ? ? ? id =downloadManager.enqueue(request)
preparListener?.onNotice?.invoke(id)
downloadListener?.onPrepare(id)
//注冊(cè)廣播啸澡,接收下載任務(wù)廣播
? ? ? ? DownloadProvider.mContext.registerReceiver(receiver,IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
downloadProgress(id)
}
fun download(url : String,name : String,deleteIfExists : Boolean =true) {
var request = DownloadManager.Request(Uri.parse(url))
request.setAllowedOverRoaming(false)
when(options.netType) {
DOWNLOAD_ONLY_PHONE -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE)
DOWNLOAD_ONLY_WIFI -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)
DOWNLOAD_NO_CARE -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
}
//設(shè)置是否顯示通知欄
? ? ? ? request.setNotificationVisibility(options.showNotify)
//設(shè)置通知欄標(biāo)題
? ? ? ? request.setTitle(options.title)
//設(shè)置通知欄簡(jiǎn)介
? ? ? ? request.setDescription(options.desc)
request.setVisibleInDownloadsUi(true)
var file = File(options.downloadPath,name)
//若已存在該文件,則刪除
? ? ? ? if (file.exists()) {
if (deleteIfExists) {
file.delete()
}else{
Log.e("download","file is exists")
return
? ? ? ? ? ? }
}
request.setDestinationUri(Uri.fromFile(file))
path = file.absolutePath
? ? ? ? id =downloadManager.enqueue(request)
preparListener?.onNotice?.invoke(id)
downloadListener?.onPrepare(id)
//注冊(cè)廣播氮帐,接收下載任務(wù)廣播
? ? ? ? DownloadProvider.mContext.registerReceiver(receiver,IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
downloadProgress(id)
}
//開協(xié)程用于監(jiān)聽下載進(jìn)度
? ? fun downloadProgress(id : Long) {
GlobalScope.launch {
? ? ? ? ? ? var breakFlag =true
? ? ? ? ? ? var query = DownloadManager.Query()
do {
query.setFilterById(id)
var cursor =downloadManager.query(query)
if (cursor.moveToFirst()) {
var bytes_downloaded = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
var bytes_total = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
var dl_progress = (bytes_downloaded *100 / bytes_total)
withContext(Dispatchers.Main){
? ? ? ? ? ? ? ? ? ? ? ? downloadingListener?.onNotice?.invoke(dl_progress)
downloadListener?.onDownloading(dl_progress)
}
? ? ? ? ? ? ? ? when {
dl_progress ==100 -> breakFlag =false
? ? ? ? ? ? ? ? ? ? cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL -> breakFlag =false
? ? ? ? ? ? ? ? ? ? cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED -> breakFlag =false
? ? ? ? ? ? ? ? }
}
cursor.close()
delay(200)
}while (breakFlag)
}
? ? }
//廣播接受者嗅虏,接收下載任務(wù)的廣播
? ? private var receiver =object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
var query = DownloadManager.Query()
query.setFilterById(id)
var cursor =downloadManager.query(query)
if (cursor.moveToFirst()) {
when(cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
//正在下載
? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_RUNNING -> {
}
//下載失敗
? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_FAILED -> {
downloadFailListener?.onNotice?.invoke()
downloadListener?.onFail()
cursor.close()
DownloadProvider.mContext.unregisterReceiver(this)
}
//下載暫停
? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_PAUSED -> {
downloadPauseListener?.onNotice?.invoke()
downloadListener?.onPaused()
}
//下載成功
? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_SUCCESSFUL -> {
downloadSuccessListener?.onNotice?.invoke(path)
downloadListener?.onSuccess(path)
cursor.close()
DownloadProvider.mContext.unregisterReceiver(this)
}
//下載延遲
? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_PENDING -> {
downloadPenddingListener?.onNotice?.invoke()
downloadListener?.onPending()
}
}
}
}
}
//立即安裝app
fun installApk(path : String) {
DownloadProvider.mContext.startActivity(Intent().apply {
? ? ? ? this.action = Intent.ACTION_VIEW
? ? ? ? this.flags = Intent.FLAG_ACTIVITY_NEW_TASK
? ? ? ? this.setDataAndType(Uri.parse(path),"application/vnd.android.package-archive")
})
}
fun installApk(path : Uri) {
DownloadProvider.mContext.startActivity(Intent().apply {
? ? ? ? this.action = Intent.ACTION_VIEW
? ? ? ? this.flags = Intent.FLAG_ACTIVITY_NEW_TASK
? ? ? ? this.setDataAndType(path,"application/vnd.android.package-archive")
})
}
class DownloadBaseListener (onNotice : (value :T) -> Unit) {var onNotice = onNotice }
class DownloadNoteListener(onNotice : () -> Unit) {var onNotice = onNotice }
interface DownloadListener {
open fun onPrepare(id: Long) {}
open fun onDownloading(progress : Int) {}
open fun onFail() {}
open fun onPaused() {}
open fun onSuccess(path : String) {}
open fun onPending() {}
}
//用于存儲(chǔ)下載時(shí)所需的配置
? ? class DownloadOptions(showNotify : Int = DownloadManager.Request.VISIBILITY_HIDDEN,title : String ="",desc : String ="") {
//是否展示通知欄
? ? ? ? var showNotify = showNotify
//通知欄標(biāo)題
? ? ? ? var title = title
//通知欄簡(jiǎn)介
? ? ? ? var desc = desc
//下載環(huán)境
? ? ? ? var netType =DOWNLOAD_NO_CARE
? ? ? ? //下載存儲(chǔ)地址
? ? ? ? var downloadPath = DownloadProvider.mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
companion object {
//網(wǎng)絡(luò)環(huán)境
? ? ? ? ? ? const val DOWNLOAD_ONLY_PHONE ="phone"
? ? ? ? ? ? const val DOWNLOAD_ONLY_WIFI ="wifi"
? ? ? ? ? ? const val DOWNLOAD_NO_CARE ="noCare"
? ? ? ? }
}
//用于獲取全局上下文
? ? class DownloadProvider : ContentProvider() {
companion object {
lateinit var mContext : Context
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
return null
? ? ? ? }
override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? {
return null
? ? ? ? }
override fun onCreate(): Boolean {
mContext =context!!
return false
? ? ? ? }
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?): Int {
return 0
? ? ? ? }
override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int {
return 0
? ? ? ? }
override fun getType(uri: Uri): String? {
return null
? ? ? ? }
}
}
```