安卓笔记-使用DownloadManager下载器封装

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

/**
 *@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<Long>? = null
    //下载中监听器,回调参数为下载进度,范围在0~100
    var downloadingListener : DownloadBaseListener<Int>? = null
    //下载失败监听器
    var downloadFailListener : DownloadNoteListener? = null
    //下载延迟监听器
    var downloadPenddingListener : DownloadNoteListener? = null
    //下载暂停监听器
    var downloadPauseListener : DownloadNoteListener? = null
    //下载成功监听器,回调参数为本地存储路径
    var downloadSuccessListener : DownloadBaseListener<String>? = null

    //下载周期监听器
    var downloadListener : DownloadListener? = null

    //下载id
    var id = 0L
    //下载地址
    var path = ""

    companion object {
        val instance : DownloadHelper by 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<Long>) {
            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<T> (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<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? {
            return null
        }

        override fun onCreate(): Boolean {
            mContext = context!!
            return false
        }

        override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?): Int {
            return 0
        }

        override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
            return 0
        }

        override fun getType(uri: Uri): String? {
            return null
        }

    }


}
发布了6 篇原创文章 · 获赞 0 · 访问量 85

猜你喜欢

转载自blog.csdn.net/u011997929/article/details/104992045