Android 11使用File.listFiles()获取Download目录文件不全如何解决
问题根因
Android 11(API 30)引入了分区存储强制规则,普通动态申请的READ_EXTERNAL_STORAGE权限仅允许访问公共目录下的媒体类文件(音频、图片、视频),这就是你只能识别.mp3、.jpg格式文件的原因。你配置的MANAGE_EXTERNAL_STORAGE属于特殊权限,无法通过普通的requestPermissions()方法申请,所以该权限实际未生效。
修复方案
方案1:申请全量文件访问权限(适合文件管理类应用)
注意:该权限属于敏感权限,Google Play上架时仅允许文件管理、杀毒、备份等必须访问全量存储的应用通过审核,非相关场景不建议使用。
- 调整
AndroidManifest.xml权限配置:
<!-- 适配Android 9及更低版本 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <!-- Android 11及以上全量存储权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- 改用特殊权限申请逻辑,跳转到系统设置页让用户手动授权:
// 自定义请求码 private static final int MANAGE_STORAGE_REQUEST = 1001; private void checkStoragePermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Environment.isExternalStorageManager()) { // 已获授权,直接读取文件 loadDownloadFiles(); } else { // 跳转权限申请页 Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(Uri.parse("package:" + getPackageName())); startActivityForResult(intent, MANAGE_STORAGE_REQUEST); } } else { // Android 10及以下走普通动态权限申请 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { loadDownloadFiles(); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, EXTERNAL_REQUEST); } } } private void loadDownloadFiles() { File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); File[] files = path.listFiles(); // 后续处理文件逻辑 }
- 在
onActivityResult回调中判断用户是否授权,授权通过后再执行读取逻辑。
方案2:使用存储访问框架(SAF,适配所有场景,无需特殊权限)
如果你的应用不需要全量存储访问权限,优先用该方案,可避免Google Play审核风险:
- 调用系统文件选择器让用户授权访问Download目录:
private static final int SAF_REQUEST = 1002; private void requestDownloadAccess() { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); // 默认定位到Download目录 intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)); startActivityForResult(intent, SAF_REQUEST); }
- 授权后在回调中拿到目录URI,通过
ContentResolver即可查询该目录下所有类型的文件,不受格式限制。
补充说明
- 如果你仅需要访问本应用下载到Download目录的文件,无需申请任何权限,直接通过
MediaStore查询本应用写入的文件即可。 - Android 11及以上不建议继续使用
File#listFiles()访问公共目录,非必要场景优先使用SAF方案,更符合系统权限规范。
内容的提问来源于stack exchange,提问作者DCuser
相关产品推荐
相关产品推荐

