使用 Android DownloadManager 下载和安装 apk 文件
最编程
2024-04-27 07:01:58
...
一、创建下载任务,并开始下载
fun downLoadFileOnBackground(
context: Context,
downTitle: String,
downDescription: String,
fileUrl: String,
fileName: String
): Long {
LogUtils.i("文件路径:${fileName}")
val request = DownloadManager.Request(Uri.parse(fileUrl))
//下载中和下载完后都显示通知栏
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
//使用系统默认的下载路径 此处为应用内 /android/data/packages ,所以兼容7.0
request.setDestinationInExternalFilesDir(
context,
Environment.DIRECTORY_DOWNLOADS,
fileName
)
//通知栏标题
request.setTitle(downTitle)
//通知栏描述信息
request.setDescription(downDescription)
//设置类型为.apk
request.setMimeType("application/vnd.android.package-archive");
//获取下载任务ID
val dm = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
return dm.enqueue(request)
}
该函数返回的是taskid
二、创建recever监听下载
class DownloadReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
installApk(context, id)
} else if (intent.action.equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
// DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
//获取所有下载任务Ids组
//long[] ids = intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
//点击通知栏取消所有下载
//manager.remove(ids);
//Toast.makeText(context, "下载任务已取消", Toast.LENGTH_SHORT).show();
//处理 如果还未完成下载,用户点击Notification ,跳转到下载中心
LogUtils.i("点击消息栏,开始安装")
val viewDownloadIntent = Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
viewDownloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(viewDownloadIntent)
}
}
private fun installApk(context: Context, downloadApkId: Long) {
LogUtils.i("下载完成,开始安装")
//判断是否允许安装未知来源安装包
if (FileUtils.isCanInstallUnKnowSource()) {
//安装apk
val dManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadFileUri = dManager.getUriForDownloadedFile(downloadApkId)
FileUtils.installApkFile(context, null, downloadFileUri)
} else {
FileUtils.requestInstallUnKnowSource(context)
}
}
}
在activity中注册和取消注册
private val downLoadReceiver by lazy { DownloadReceiver() }
registerReceiver(downLoadReceiver, intentFilter, RECEIVER_NOT_EXPORTED)
unregisterReceiver(downLoadReceiver)
三、fileProvider适配
manifest.xml中
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
xml文件夹下创建file_path.xml文件
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!--增加根目录配置,特别注意:此处的path要为空字符串-->
<root-path
name="root_path"
path="" />
<external-files-path
name="files_download"
path="Download" />
</paths>
因为安装apk文件用到一些系统文件下的内容,所以增加了root-path的访问,
由于未设置root-path的访问,可能在安装apk时提示解析安装包文件出现问题的提示
四、下载完成之后安装apk文件
fun installApkFile(context: Context, file: File?, fileUri: Uri?) {
if (file == null && fileUri == null) {
return
}
//打开安装界面
val intent = Intent(Intent.ACTION_VIEW)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
if (file != null) {
if (file.name.endsWith(".apk")) {
val apkUri =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
FileProvider.getUriForFile(
context,
context.packageName + ".fileProvider",
file
)
} else {
Uri.fromFile(file)
}
intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
}
} else if (fileUri != null) {
intent.setDataAndType(fileUri, "application/vnd.android.package-archive")
}
context.startActivity(intent)
}
上一篇: 上传和下载鳄梨酱
推荐阅读
-
使用 Android DownloadManager 下载和安装 apk 文件
-
iCloud 切换区域,中国区保留 appStore(更新)--自 2018 年 2 月 28 日起,中国区 iCloud 由云上贵州管理 苹果公司发布的公告 https://support.apple.com/zh-cn/HT208352 关键词 关键部分 受影响的 iCloud 账户:国家或地区设置为 "中国 "的 Apple ID。 iCloud 包含的服务照片、邮件、通讯录、日历、提醒事项、备忘、书签、钱包、钥匙串、云备份、云驱动器、应用程序数据 新条款和条件: 同意仅出于本协议允许的目的并在中国法律允许的范围内使用服务。 云桂洲在提供服务时应使用合理的技能并尽职尽责,但在适用法律允许的最大范围内,我们不保证或担保您通过本服务存储或访问的任何内容不会意外损坏、崩溃、丢失或根据本协议的条款被删除,如果发生此类损坏、崩溃、丢失或删除,我们不承担任何责任。您应自行负责维护您的信息和数据的适当备份。 Apple 和云上贵州有权访问您存储在服务中的所有数据,包括有权根据适用法律相互之间共享、交换和披露所有用户数据(包括内容)。 本协议的解释、效力和履行应适用*法律。对于因本协议引起的或与本协议有关的任何争议,云桂洲和您同意提交中国国际经济贸易仲裁委员会(CIETAC)根据提交仲裁时有效的法律在北京进行具有约束力的仲裁。 由云桂洲管理,用户选择: 停用; ID 到地区; 受 iCloud(由云桂洲运营)条款和条件约束 首先,我想说说我对数据安全的看法。 当我在朋友圈发布通知时,有些朋友回复说国外的操作并没有多安全,或者国外的安全只是相对于国外而言的等等。首先,我非常感谢这些朋友,这让我反思什么是数据安全。以下观点均属个人观点: 国外的月亮一定比国内圆? 这是一个根深蒂固的问题,只要有人说国外的东西比国内好,就会有人嘲笑崇洋媚外。我觉得我们在某些方面应该向国外学习,比如搜索引擎和版权问题。打开百度搜索 "数据安全",第一行肯定是广告。打开谷歌搜索 "数据安全",第一条就是 "数据安全_百度百科" .....各种版权问题大家都明白,支持正版,但不仅客户一心想找免费破解,就连作者也往往没有保护自己劳动成果或产品的想法。但从另一个层面来说,国内的发展和安全,甩国外几条街。没有说哪里好,哪里不好,辩证地去学习更好。 国外也有别有用心的数据泄露,谈何安全? 从加密解密的角度看,自古以来就没有绝对安全的加密,只有相对安全的做法。苹果的棱镜门、微软的 cpu 漏洞,各种参差不齐的被破解案例 ....是的,这的确是一个很好的论据,但凡事都不能只看一面,当年苹果面对FBI破解手机的要求,几经论证,苹果还是拒绝破解。这点拿到国内,只要上面的文件传达下去,还有企业敢说不吗?还敢说不吗? 关于这次iCloud数据迁移个人看法? 把数据迁移到贵州的云端,相当于把手机的所有数据都存储在贵州的云端服务器上。也许访问数据的速度会快很多,但我会把我的iCloud区放到美国,因为我不想数据存在云上贵州后经常接到莫名其妙的电话或短信,更不想因为乱用国外服务器而被请去喝茶。iCloud一个ID,即从中国账号转到美国区,主要用于数据存在美国服务器上。appStore一个ID,除了注册一个中国ID外,专门用来下载应用用,因为国外ID不支持酷狗和网易云等应用。麻烦的是,用了新的 appStore ID 后,当前的应用还得重新下载安装,因为旧的应用 ID 与新的应用 ID 不兼容,安装不了。最后,iCloud迁移后,国内用户使用美国服务器,估计要 "扶墙 "了。 专业步骤: 首先,进行appleID设置,这是前提条件,否则无法选择转移区域! 取消 appleID 的双重认证 取消家庭共享选项 二、窗口下载并安装 icloud 3.0 版
-
JMeter安装与使用:附带下载文件和TPS工具
-
Jmeter安装使用(附下载文件和TPS工具)
-
使用Docker安装Minio并实现文件的上传、删除和下载