apk下载与BroadcastReceiver自动安装

该博客介绍了如何在Android中实现apk的下载,并通过BroadcastReceiver自动安装。内容包括在清单文件中注册BroadcastReceiver,设置必要的权限,进行apk下载操作,以及BroadcastReceiver的安装逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

apk下载与BroadcastReceiver自动安装

清单文件注册
AndroidManifest-清单文件

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:resizeableActivity="true"
        android:supportsRtl="true"
        android:theme="@style/BaseThemes1">
        <!--Android7.0及其以上provider适配-->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities=""  //应用包名
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

        <receiver
            android:name=".receiver.DownloadCompleteReceiver"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
            </intent-filter>
        </receiver>

权限检查(定义路径)

/**
* 检查权限
* 版本判断
* 定义目录
*/
private fun update(url: String, context: Context) {
	if (TextUtils.isEmpty(url)) {
		return
	}
	checkPermission(context) {
		//版本适配,定义路径
		val name = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
		
			InitApp.initApp.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.absolutePath.toString()
		} else {
			Environment.getExternalStorageDirectory().absolutePath
		}
		downloadPosition(url, context, name)
	}
}



/**
* 检查权限
*/
private fun checkPermission(context: Context, go: () -> Unit) {
	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
		go()
	} else {
		XXPermissions.with(context as Activity)
			.permission(Permission.Group.STORAGE) //不指定权限则自动获取清单中的危险权限
			.request(object : OnPermission {
				override fun hasPermission(granted: List<String?>?, isAll: Boolean) {
					if (isAll) {
						go()
					}
				}
				
				override fun noPermission(denied: List<String?>?, quick: Boolean) {
					toast("请允许申请权限,才能执行本次操作")
				}
			})
	}
    }

apk下载



/**
* 下载apk
*/
private fun downloadPosition(url: String, context: Context, name: String) {
	try {
		//获取组件的方法
		val state: Int = context.packageManager.getApplicationEnabledSetting("com.android.providers.downloads")
		
		if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
			val intent = Intent(Intent.ACTION_VIEW)
			intent.data = Uri.parse(url)
			context.startActivity(intent)
		} else {
			val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager //初始化DownloadManager
			val request = DownloadManager.Request(Uri.parse(url))//设置下载地址
			//下载路径
			var name = name
			name += "/scidownload/"
			val dir = File(name)
			if (!dir.exists()) {
				dir.mkdirs()
			}
			//若存在此目录,就删除
			val dir1 = File(name + PackageUtils.getPackageName(context).toString() + ".apk")
			if (dir1.exists()) {
				dir1.delete()
			}
			
			val dest = Uri.fromFile(File(name + PackageUtils.getPackageName(context).toString() + ".apk"))
			request.apply {
				setDestinationUri(dest)
				setTitle("正在下载")//设置notification的title信息
				setDescription("***")//设置notification的message信息
				setMimeType("application/vnd.android.package-archive")//是apk的mime类型
				setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)//设置通知栏下载通知显示状态
			}
			//将请求文件下载的Uri传递给DownloadManager的enqueue方法
			// downloadId是系统为当前的下载请求分配的唯一的id,我们可以通过这个id重新获得这个下载任务
			val downloadId = downloadManager.enqueue(request)
			PrefUtils.putLong(context, InitApp.DOWNLOAD_TASK_PREF, InitApp.DOWNLOAD_TASK_ID_KEY, downloadId) //获取完成下载任务的id
		}
	} catch (e: java.lang.Exception) {
		val intent = Intent(Intent.ACTION_VIEW)//是Android系统内置的动作,常量值为Intent.ACTION_VIEW
		intent.data = Uri.parse(url)//通过Uri.parse()方法将一个网址字符串解析成一个Uri对象,通过Intent的setData()方法将这个Uri传递进去
		context.startActivity(intent)
	}
}

Broadcastreceiver自动安装

class DownloadCompleteReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == DownloadManager.ACTION_DOWNLOAD_COMPLETE) {
            val downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)//获取完成下载任务的id
            if (downId == PrefUtils.getLong(context, InitApp.DOWNLOAD_TASK_PREF, InitApp.DOWNLOAD_TASK_ID_KEY, 0)) {//如果获取到下载任务的id匹配缓存到app中的下载id
                toast("下载完成!")
                var file: File? = null
                //定义apk路径名称
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    file = File(InitApp.initApp.getDOWNLOAD_POSITION().toString() + "/scidownload/" + PackageUtils.getPackageName(context) + ".apk")
                } else {
                    file = File(Environment.getExternalStorageDirectory().absolutePath + "/scidownload/" + PackageUtils.getPackageName(context) + ".apk")
                }
                installApk(context, context.applicationContext.packageName, file)
            }
        }

    }

    companion object {
        /**
         * 安装一个apk
         *
         * @param context     上下文
         * @param authorities Android N 授权
         * @param apk         安装包文件
         */
        fun installApk(context: Context, authorities: String?, apk: File?) {
            val intent = Intent(Intent.ACTION_VIEW)
            intent.action = Intent.ACTION_VIEW
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            intent.addCategory(Intent.CATEGORY_DEFAULT)
            val uri: Uri
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                uri = FileProvider.getUriForFile(context, authorities!!, apk!!)
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            } else {
                uri = Uri.fromFile(apk)
            }
            intent.setDataAndType(uri, "application/vnd.android.package-archive")
            context.startActivity(intent)
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值