Android 11及以上如何通过Scope Storage获取下载目录的APK文件并安装
适配方案
核心前提:你的场景完全不需要申请MANAGE_EXTERNAL_STORAGE权限,Android 11+ 允许应用访问自身下载到公共目录的文件、以及应用专属目录的所有文件,仅需少量配置即可满足需求。
方案1:直接使用系统DownloadManager返回的URI(最推荐)
使用系统DownloadManager下载时,无需手动查询文件,可直接获取官方授权的可用URI,适配成本最低。
- 首先在
AndroidManifest.xml中配置必要权限:
<!-- 安装APK必要权限,全Android版本适用 --> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <!-- 存储权限仅Android 12及以下需要,Android 13+无需申请 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
- 调用DownloadManager发起下载时,记录返回的唯一
downloadId - 监听
DownloadManager.ACTION_DOWNLOAD_COMPLETE广播,收到下载完成通知后,直接通过downloadId获取对应文件的URI:
val downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager val apkUri = downloadManager.getUriForDownloadedFile(downloadId)
- 该URI已经被系统临时授予你的应用访问权限,可直接传给包管理器使用。
方案2:通过MediaStore查询公共Download目录的自有文件
如果没有保留downloadId,需要手动查询你下载到公共Download目录的APK,使用MediaStore即可实现,无需额外存储权限:
- 查询的目标URI固定为
MediaStore.Downloads.EXTERNAL_CONTENT_URI - 查询时可添加过滤条件:匹配文件名、下载时间,或者添加
MediaStore.Downloads.OWNER_PACKAGE_NAME = "你的应用包名"过滤仅返回你自己应用下载的文件,Android 10+支持该字段。 - 查询到目标文件的ID后,拼接出可用的Content URI:
val apkUri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, 目标文件ID)
方案3:使用应用专属目录存储下载文件(自定义下载逻辑适用)
如果你是自己实现下载逻辑而非使用系统DownloadManager,直接将APK存储到应用专属外部存储目录即可:
- 目标目录路径:
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),该目录下的文件你的应用可以自由读写,不需要任何存储权限。 - 配置FileProvider将本地文件路径转换为Content URI,即可传给包管理器安装。
发起APK安装的代码实现
拿到可用的URI后,按如下逻辑发起安装请求即可:
val installIntent = Intent(Intent.ACTION_VIEW).apply { setDataAndType(apkUri, "application/vnd.android.package-archive") // 给包管理器授予URI临时读取权限,必须添加 addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } startActivity(installIntent)
Google Play审核注意事项
- 完全移除
MANAGE_EXTERNAL_STORAGE权限的Manifest声明和申请逻辑,该权限与你的场景完全无关 - 若审核时被问及
REQUEST_INSTALL_PACKAGES权限的用途,直接说明是用于应用内下载更新自身APK即可,符合Play商店政策要求。
内容的提问来源于stack exchange,提问作者Muhammad Ali
相关产品推荐
相关产品推荐

