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