Android开发:如何调用系统文件管理器选择文件夹而非文件?
Android 系统文件管理器选择文件夹的实现方案
嘿,这个需求我之前做项目的时候刚好碰到过!你当前用的Intent.ACTION_GET_CONTENT确实是专门用来选择文件的,要实现文件夹选择,得换个官方推荐的Intent Action,而且不同Android版本的适配细节有点不一样,我给你一步步讲清楚:
核心方案:使用ACTION_OPEN_DOCUMENT_TREE
从Android 5.0(API 21)开始,系统就提供了Intent.ACTION_OPEN_DOCUMENT_TREE这个Action,专门用来让用户选择文件夹,这也是官方推荐的标准方式,兼容性最好。
1. 基础调用代码(替代你原来的代码)
把你原来的Intent代码替换成下面这样:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); // 可选设置:指定打开文件管理器时的初始目录(比如下载目录,API 29+支持) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { Uri initialUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY); intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri); } // 如果你还在用旧的startActivityForResult(不推荐,已废弃) // startActivityForResult(intent, REQUEST_CODE_FOLDER); // 推荐用AndroidX的ActivityResultLauncher(适配最新API) folderPickerLauncher.launch(intent);
2. 处理选择结果(推荐用ActivityResultLauncher)
因为startActivityForResult已经被官方废弃了,我直接给你最新的实现方式:
// 在Activity/Fragment的onCreate里初始化Launcher ActivityResultLauncher<Intent> folderPickerLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { Uri selectedFolderUri = result.getData().getData(); if (selectedFolderUri != null) { // 重要:持久化文件夹的访问权限,避免重启APP后失去权限 getContentResolver().takePersistableUriPermission( selectedFolderUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION ); // 用DocumentFile来操作选中的文件夹 DocumentFile selectedFolder = DocumentFile.fromTreeUri(this, selectedFolderUri); if (selectedFolder != null && selectedFolder.isDirectory()) { // 示例:遍历文件夹里的所有文件 for (DocumentFile file : selectedFolder.listFiles()) { Log.d("FolderPicker", "文件名:" + file.getName() + ",路径URI:" + file.getUri()); } } } } } );
低版本兼容(API 21以下)
如果你的APP需要兼容Android 4.4及以下版本,ACTION_OPEN_DOCUMENT_TREE是不支持的,这时候可以尝试用下面的方案,但注意兼容性可能不如官方方案:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("vnd.android.document/directory"); intent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(intent, REQUEST_CODE_FOLDER);
不过这个方式依赖厂商的ROM实现,有些定制系统可能不支持,所以如果你的用户群体主要是Android 5.0以上,优先用ACTION_OPEN_DOCUMENT_TREE就好。
注意事项
- 权限问题:使用
ACTION_OPEN_DOCUMENT_TREE不需要申请READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE权限,因为是通过系统文件管理器授予的URI级别的权限,而且通过takePersistableUriPermission可以持久化这个权限。 - Scoped Storage适配:Android 10及以上的Scoped Storage机制下,这种方式是唯一合规的访问外部文件夹的方式,避免了直接操作文件路径的限制。
内容的提问来源于stack exchange,提问作者dezhihuang




