Android 11及以上系统如何访问Download下载目录下的所有文件
Android 11及以上获取公共下载目录全量文件解决方案
Android 11开始系统强制启用分区存储机制,普通存储权限仅允许访问当前应用自身创建的公共目录文件,无法读取其他应用生成的下载目录文件,因此原有File API调用只能获取到部分文件。
方案1:申请全文件管理权限(适配原有File API逻辑)
该方案可以让原有listFiles()逻辑完全复用,无需修改文件读取逻辑。
操作步骤
- 在
AndroidManifest.xml中添加权限及适配配置:
<!-- 原有读写权限保留 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Android 11+全文件访问权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <application ... <!-- 兼容Android 10以下版本 --> android:requestLegacyExternalStorage="true"> ... </application>
- 动态引导用户开启权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // 检查是否已经获得全文件管理权限 if (!Environment.isExternalStorageManager()) { // 跳转到应用权限设置页引导用户开启 val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) intent.data = Uri.parse("package:${packageName}") startActivityForResult(intent, REQUEST_MANAGE_STORAGE_CODE) } else { // 已获得权限,原有listFiles逻辑可正常执行 val files: Queue<File> = LinkedList() val ROOT_DIR = getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath files.addAll(File(ROOT_DIR).listFiles()) } } else { // 低于Android 11版本直接执行原有逻辑 val files: Queue<File> = LinkedList() val ROOT_DIR = getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath files.addAll(File(ROOT_DIR).listFiles()) }
适用场景
仅适合文件管理器、垃圾清理、文档编辑等核心功能必须访问全量存储的应用,上架谷歌Play商店需提交权限使用说明,符合平台政策才可过审。
方案2:使用MediaStore查询(无需特殊权限)
该方案无需申请全文件管理权限,仅需普通存储权限即可获取下载目录全量文件,更易通过应用商店审核。
代码实现
val downloadFileList = mutableListOf<File>() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val projection = arrayOf( MediaStore.Downloads._ID, MediaStore.Downloads.DISPLAY_NAME, MediaStore.Downloads.DATA, MediaStore.Downloads.SIZE ) val sortOrder = "${MediaStore.Downloads.DATE_ADDED} DESC" contentResolver.query( MediaStore.Downloads.EXTERNAL_CONTENT_URI, projection, null, null, sortOrder )?.use { cursor -> while (cursor.moveToNext()) { val filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Downloads.DATA)) downloadFileList.add(File(filePath)) } } } else { // 低版本沿用原有逻辑 val ROOT_DIR = getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath downloadFileList.addAll(File(ROOT_DIR).listFiles().toList()) } // 最终downloadFileList即为下载目录下所有文件列表
适用场景
适合绝大多数仅需要读取下载目录文件的普通应用,无需申请特殊权限,适配成本低。
注意事项
- 若采用方案1上架谷歌Play,必须证明全文件管理权限是应用核心功能必需项,无合理使用场景的应用会被拒绝上架。
- Android 13及以上版本读取非自身创建的媒体文件,需额外申请对应照片/视频/音频权限,读取下载目录的非媒体文件仍可通过MediaStore正常获取。
内容的提问来源于stack exchange,提问作者Kishore Reddy
相关产品推荐
相关产品推荐

