Flutter Android 13(SDK33)存储权限申请失败问题求助
解决Android 13(SDK33)Flutter存储权限与目录创建失败问题
一、权限问题根源与修正
Android 13(SDK33)彻底移除了READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE的用户授权入口,拆分出READ_MEDIA_IMAGES、READ_MEDIA_AUDIO、READ_MEDIA_VIDEO三个细分媒体权限。Permission.storage在SDK33+环境下完全失效,所以调用后永远返回false。
你的场景是处理录音文件,SDK33+应申请Permission.audio(对应系统的READ_MEDIA_AUDIO权限)而非Permission.photos。修正后的权限申请代码:
bool permissionGranted = false; if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt <= 32) { Map<Permission, PermissionStatus> permissions = await [ Permission.storage, Permission.microphone, ].request(); permissionGranted = permissions[Permission.storage]!.isGranted && permissions[Permission.microphone]!.isGranted; } else { Map<Permission, PermissionStatus> permissions = await [ Permission.audio, // 替换为音频权限,匹配录音文件场景 Permission.microphone, ].request(); permissionGranted = permissions[Permission.audio]!.isGranted && permissions[Permission.microphone]!.isGranted; } }
二、目录创建失败的核心原因
/storage/recordings属于外部存储公共根目录,从Android 10(API29)开始,分区存储机制限制APP直接访问该路径,即便授予媒体权限也无法创建目录。requestLegacyExternalStorage="true"仅在API29-30版本生效,SDK33+完全失效。
两种可行的目录方案:
方案1:应用专属外部存储目录(推荐,无需额外权限)
该目录属于APP私有空间,卸载时自动删除,无需申请媒体权限:
// 需要先添加path_provider依赖:path_provider: ^2.0.15(或最新版本) Directory directory = Directory('${(await getExternalStorageDirectory())!.path}/Recordings'); await directory.create(recursive: true);
路径示例:Android/data/com.example.keyword_speech/files/Recordings
方案2:公共媒体目录(适合需要用户在系统文件管理器可见的场景)
如果要将录音放在公共音频目录下:
Directory directory = Directory('${(await getExternalStorageDirectory())!.parent.parent.parent}/Music/Recordings'); await directory.create(recursive: true);
路径示例:/storage/emulated/0/Music/Recordings,需确保已授予Permission.audio权限。
三、AndroidManifest.xml清理优化
移除冗余权限,避免系统权限映射混淆:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.keyword_speech"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- 仅对SDK32及以下保留存储权限,SDK33+自动忽略 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <!-- SDK33+音频媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!-- 非文件管理器类应用不要使用该权限,谷歌审核会拒绝 --> <!-- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> --> <application ... android:requestLegacyExternalStorage="true"> ... </application> </manifest>
四、额外注意事项
MANAGE_EXTERNAL_STORAGE权限仅对文件管理器、备份工具等特定类型应用开放,普通应用申请会被谷歌Play审核拒绝,尽量避免使用。- 若必须访问公共根目录,需通过
openAppSettings()跳转应用设置页面,引导用户手动开启“所有文件访问权限”,但此方式不推荐。
内容的提问来源于stack exchange,提问作者jadekim
相关产品推荐
相关产品推荐

