Android TargetSdk33下SD卡目录创建失败,权限问题求助
Android 13(TargetSdk33)存储权限变更导致目录创建失败的解决方案
问题根源
Android 13(API 33)彻底调整了外部存储权限规则:
- 旧的
WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE权限已被废弃,不再生效。 - 应用无法直接在
Environment.getExternalStorageDirectory()指向的公共存储根目录创建自定义文件夹(比如你代码里的/Temp),系统会直接拒绝这类操作。
分场景解决方法
场景1:存储应用私有文件(推荐)
如果这些文件不需要被其他应用访问,直接用应用专属外部存储目录,完全不需要申请权限:
// 路径示例:/storage/emulated/0/Android/data/com.export.exportcontacts/files/Temp File directory = new File(getExternalFilesDir(null), "Temp"); if (!directory.exists()) { boolean isCreated = directory.mkdirs(); // 可打印isCreated值确认是否创建成功 }
这个目录的文件会随应用卸载自动删除,符合Android的存储最佳实践。
场景2:必须写入公共存储目录(非媒体文件)
如果一定要在公共区域创建目录,只能用**存储访问框架(SAF)**让用户手动选择目录授权:
- 启动目录选择界面:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(intent, 1001);
- 处理用户选择结果并创建目录:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1001 && resultCode == RESULT_OK && data != null) { Uri treeUri = data.getData(); // 申请持久化权限,下次启动不用再选目录 getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // 在选中的目录下创建Temp文件夹 DocumentFile rootDir = DocumentFile.fromTreeUri(this, treeUri); DocumentFile tempDir = rootDir.createDirectory("Temp"); // tempDir就是创建好的目录对象 } }
场景3:存储媒体文件(图片/音频/视频)
如果是存媒体类文件,先替换Manifest里的权限:
<!-- 图片权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.WRITE_MEDIA_IMAGES" /> <!-- 音频权限 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <uses-permission android:name="android.permission.WRITE_MEDIA_AUDIO" /> <!-- 视频权限 --> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.WRITE_MEDIA_VIDEO" />
然后用MediaStore API写入文件,不要直接操作File对象。
兼容低版本设备的注意事项
如果要兼容API 32及以下设备,Manifest里可以保留旧权限但加上版本限制:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
同时,低版本设备需要动态申请WRITE_EXTERNAL_STORAGE权限,API 33及以上则只需动态申请对应的媒体权限,SAF方式无需权限申请但需要用户手动选目录。
内容的提问来源于stack exchange,提问作者Anatoli
相关产品推荐
相关产品推荐

