DownloadManager实现Apk下载更新

东明德
2023-12-01
/**
 * 专用下载APK文件Service工具类,通知栏显示进度,下载完成自动安装
 */
class UpdateService : Service() {

    /**
     * 安卓系统下载类
     */
    private var manager: DownloadManager by Delegates.notNull()

    /**
     * 接收下载完的广播
     */
    private var mDownloadReceiver: DownloadCompleteReceiver by Delegates.notNull()

    /**
     * 初始化下载器
     */
    private fun initDownManager(url: String) {
        Log.i("tt", "initDownManager")
        manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager

        mDownloadReceiver = DownloadCompleteReceiver()

        //设置下载地址
        val down = DownloadManager.Request(
                //下载链接
                Uri.parse(url))

        // 设置允许使用的网络类型,这里是移动网络和wifi都可以
        down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)

        // 下载时,通知栏显示途中
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
        }

        // 显示下载界面
        down.setVisibleInDownloadsUi(true)

        // 设置下载后文件存放的位置
        down.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "my_app.apk")

        // 将下载请求放入队列
        manager.enqueue(down)

        //注册下载广播
        registerReceiver(mDownloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {

        val url = intent.getStringExtra("url")
        // 调用下载
        initDownManager(url)

        return super.onStartCommand(intent, flags, startId)
    }

    override fun onBind(intent: Intent): IBinder? {

        return null
    }

    override fun onDestroy() {
        // 注销下载广播
        unregisterReceiver(mDownloadReceiver)
        super.onDestroy()
    }

    // 接受下载完成后的intent
    internal open inner class DownloadCompleteReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {

            //判断是否下载完成的广播
            if (intent.action == DownloadManager.ACTION_DOWNLOAD_COMPLETE) {
                Log.i("tt", "DownloadManager.ACTION_DOWNLOAD_COMPLETE")
                //获取下载的文件id
                val downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L)
                //自动安装apk
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                    val uriForDownloadedFile = manager.getUriForDownloadedFile(downId)
                    Log.i("tt", "uri=$uriForDownloadedFile")

                    installApkNew(uriForDownloadedFile)
                }
                //停止服务并关闭广播
                this@UpdateService.stopSelf()
            }
        }

        //安装apk
        private fun installApkNew(uri: Uri) {
            val intent = Intent()
            //执行动作
            intent.action = Intent.ACTION_VIEW
            //执行的数据类型
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            intent.setDataAndType(uri, "application/vnd.android.package-archive")
            //不加下面这句话是可以的,查考的里面说如果不加上这句的话在apk安装完成之后点击单开会崩溃
            // android.os.Process.killProcess(android.os.Process.myPid());
            startActivity(intent)
        }
    }
}
//启动服务
val intent = Intent(this, UpdateService::class.java)
intent.putExtra("url", url)
startService(intent)
 类似资料: