Flutter适配Android11存储权限 实现类似WhatsApp应用内授权弹窗
问题根因
你当前申请的Permission.manageExternalStorage对应Android系统的MANAGE_EXTERNAL_STORAGE权限,属于Android 11及以上新增的「所有文件访问」特殊权限,系统原生逻辑就是申请时直接跳转到系统设置页,不会弹出应用内授权弹窗,这是你当前问题的核心原因。
WhatsApp使用的是普通媒体存储权限,没有申请这个特殊权限,自然可以弹出应用内授权弹窗。
修复步骤
1. 修改AndroidManifest.xml权限配置
首先移除你项目中android/app/src/main/AndroidManifest.xml里的MANAGE_EXTERNAL_STORAGE权限声明,修改权限配置如下:
<!-- 低版本存储权限,Android 10以上写入公共目录无需该权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <!-- Android 12及以下读取公共媒体文件需要该权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- Android 13及以上按需申请对应媒体权限,不需要可以不声明 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
2. 调整权限申请代码
不要继续申请manageExternalStorage权限,按系统版本按需申请对应普通权限即可:
Future<bool> requestPermission() async { var androidInfo = await DeviceInfoPlugin().androidInfo; // 优先用sdkInt判断版本,比release字段更准确,避免定制ROM版本号异常问题 int sdkInt = androidInfo.version.sdkInt; // 如果只是将文件存储到Android/media/你的应用包名目录、或者应用专属私有目录 // Android 11及以上不需要申请任何权限,可直接返回true if (sdkInt >= 33) { // Android 13+ 按需申请你需要的媒体权限,不需要访问其他应用的媒体文件可直接返回true Map<Permission, PermissionStatus> statuses = await [ Permission.READ_MEDIA_IMAGES, Permission.READ_MEDIA_VIDEO, Permission.READ_MEDIA_AUDIO, ].request(); return statuses.values.every((status) => status.isGranted); } else { PermissionStatus status = await Permission.storage.request(); return status.isGranted; } }
补充说明
如果你的下载文件不需要对外暴露给其他应用,直接使用Flutter的path_provider插件获取getExternalFilesDir(null)对应的应用专属目录存储文件,全Android版本都不需要申请任何存储权限,实现成本更低。
内容的提问来源于stack exchange,提问作者Narayana
相关产品推荐
相关产品推荐

