安卓笔记 - 2020-03-20 - 封装下载器

下载器封装,便于开发,使用downloadManager。可以监听下载进度,监听方法里使用了协程,也可以使用线程进行监听,同时使用contentProvider来获取全局上下文,所以在使用中无需传递上下文。

此文仅用于本人记录开发经验所用。

```

/**

*@Company NSNTC

*@author Chord.p

*@time 2020/3/20 9:44 AM

*speak softly love

*

* 下载器,暂时无法管理多下载任务状态

*/

class DownloadHelper {

//下载器

    private var downloadManager : DownloadManager = DownloadProvider.mContext.getSystemService(Context.DOWNLOAD_SERVICE)as DownloadManager

//下载时相关配置

    private var options = DownloadOptions()

//下载开始监听器,回调参数为下载id,可通过该id对该下载任务进行管理

    var preparListener : DownloadBaseListener? =null

    //下载中监听器,回调参数为下载进度,范围在0~100

    var downloadingListener : DownloadBaseListener? =null

    //下载失败监听器

    var downloadFailListener : DownloadNoteListener? =null

    //下载延迟监听器

    var downloadPenddingListener : DownloadNoteListener? =null

    //下载暂停监听器

    var downloadPauseListener : DownloadNoteListener? =null

    //下载成功监听器,回调参数为本地存储路径

    var downloadSuccessListener : DownloadBaseListener? =null

    //下载周期监听器

    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)

}

/**

* 请使用DownloadOptions下的常量进行设定

*/

        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

}

/**

* 请使用DownloadManager.Request 下的常量进行设定

*/

        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)

}

//设置是否显示通知栏

        request.setNotificationVisibility(options.showNotify)

//设置通知栏标题

        request.setTitle(options.title)

//设置通知栏简介

        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)

//注册广播,接收下载任务广播

        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)

}

//设置是否显示通知栏

        request.setNotificationVisibility(options.showNotify)

//设置通知栏标题

        request.setTitle(options.title)

//设置通知栏简介

        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)

//注册广播,接收下载任务广播

        DownloadProvider.mContext.registerReceiver(receiver,IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))

downloadProgress(id)

}

//开协程用于监听下载进度

    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)

}

    }

//广播接受者,接收下载任务的广播

    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() {}

}

//用于存储下载时所需的配置

    class DownloadOptions(showNotify : Int = DownloadManager.Request.VISIBILITY_HIDDEN,title : String ="",desc : String ="") {

//是否展示通知栏

        var showNotify = showNotify

//通知栏标题

        var title = title

//通知栏简介

        var desc = desc

//下载环境

        var netType =DOWNLOAD_NO_CARE

        //下载存储地址

        var downloadPath = DownloadProvider.mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)

companion object {

//网络环境

            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

        }

}

}

```

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容