Android 10+设备如何通过路径名访问任意文件
Android 10+ 访问任意文件的实现方案
在Android 10及以上版本,系统引入了Scoped Storage机制,限制了直接通过File类访问任意路径的能力,想要实现类似旧版本的任意文件访问,可通过以下核心方式:
一、申请MANAGE_EXTERNAL_STORAGE权限(Android 11+)
这个权限能让应用获得对外部存储的完整访问权,近似回到旧版本的文件访问模式。
操作步骤:
- 在
AndroidManifest.xml中声明权限:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
- 在代码中动态申请权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); } else { // 权限已授予,可直接用File类访问任意路径 File f = new File(Environment.getExternalStorageDirectory() + "/filename.txt"); // 后续文件操作逻辑 } }
注意:Google Play对使用该权限的应用审核严格,仅允许文件管理器、备份类等确实需要完整存储访问的应用通过,普通应用慎用。
二、使用存储访问框架(SAF)让用户选择文件/目录
如果不想依赖高权限,可通过SAF让用户手动选择需要访问的文件或目录,这种方式符合Scoped Storage的设计规范,也能顺利通过Play审核。
访问单个文件:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); // 允许选择任意类型文件 startActivityForResult(intent, REQUEST_CODE_OPEN_FILE);
在onActivityResult(或AndroidX的registerForActivityResult)中获取Uri,后续通过ContentResolver操作文件:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_OPEN_FILE && resultCode == RESULT_OK) { if (data != null) { Uri uri = data.getData(); // 读取文件内容示例 try (InputStream inputStream = getContentResolver().openInputStream(uri)) { // 处理输入流 } catch (IOException e) { e.printStackTrace(); } } } }
访问整个目录:
如果需要访问某个目录下的所有文件,可申请目录访问权限:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(intent, REQUEST_CODE_OPEN_DIRECTORY);
获取目录Uri后,可通过DocumentFile遍历目录下的文件:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_OPEN_DIRECTORY && resultCode == RESULT_OK) { if (data != null) { Uri treeUri = data.getData(); // 持久化权限,重启后仍可访问 getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); DocumentFile rootDir = DocumentFile.fromTreeUri(this, treeUri); // 遍历目录文件 for (DocumentFile file : rootDir.listFiles()) { // 处理每个文件 } } } }
三、额外注意事项
- 优先使用SAF方案,符合系统安全规范,避免Play审核风险;
- Android 10可通过在
AndroidManifest.xml中设置android:requestLegacyExternalStorage="true"临时启用旧版存储访问逻辑,但该方案在Android 12及以上版本失效。
内容的提问来源于stack exchange,提问作者Vinay K
相关产品推荐
相关产品推荐

