Flutter Android获取外部存储权限问题求助(file_provider插件)
解决Flutter Android外部存储权限被拒绝(errno=13)的问题
我来帮你梳理一下这个权限问题的解决思路——你遇到的Permission denied (errno=13)错误,大多和Android不同版本的存储策略变化、权限申请流程有关,以下是几个关键的排查和修复方向:
1. 必须申请运行时动态权限
Android 6.0(API 23)及以上版本,即使在AndroidManifest.xml中声明了权限,也需要在代码中主动请求用户授权。你可以使用permission_handler包来简化这个流程:
- 首先添加依赖:
flutter pub add permission_handler - 然后在需要执行存储操作前,请求权限:
import 'package:permission_handler/permission_handler.dart'; Future<void> checkAndRequestStoragePermission() async { PermissionStatus status; // 根据Android版本选择对应的权限 if (await Permission.storage.isRestricted) { // 设备限制权限(比如儿童模式) return; } status = await Permission.storage.request(); if (status.isGranted) { // 权限已授予,执行你的目录创建/文件操作 createExternalDirectory(); } else if (status.isDenied) { // 权限被拒绝,可以提示用户开启权限 print("存储权限被拒绝,请授予权限后重试"); } else if (status.isPermanentlyDenied) { // 权限被永久拒绝,引导用户跳转到应用设置页开启 await openAppSettings(); } }
2. 适配Android 10+的分区存储(Scoped Storage)
Android 10(API 29)默认启用了分区存储,即使你声明了WRITE_EXTERNAL_STORAGE,也无法直接访问外部存储的根目录自定义文件夹。解决方式分两种:
- 针对API 29(Android 10):在
AndroidManifest.xml的<application>标签中添加属性,临时禁用分区存储:<application android:name="io.flutter.app.FlutterApplication" ... android:requestLegacyExternalStorage="true"> <!-- 其他配置 --> </application> - 针对API 30+(Android 11及以上):
requestLegacyExternalStorage不再生效。如果需要访问应用专属目录之外的文件,你有两个选择:- 优先使用应用专属外部存储目录:用
path_provider包获取这个目录,不需要额外权限,代码示例:import 'package:path_provider/path_provider.dart'; Future<String> getAppExternalDir() async { final directory = await getExternalStorageDirectory(); return directory?.path ?? ""; } - 如果必须访问共享目录(比如下载、图片文件夹)或其他应用的文件,需要申请
MANAGE_EXTERNAL_STORAGE权限,并引导用户手动在设置中开启(这个权限上架Google Play需要符合特定政策,谨慎使用):<!-- 在AndroidManifest.xml中添加权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />// 动态请求权限 final status = await Permission.manageExternalStorage.request();
- 优先使用应用专属外部存储目录:用
3. 检查目标SDK版本
如果你的targetSdkVersion设置为30及以上,WRITE_EXTERNAL_STORAGE权限已经被废弃:
- 对于媒体文件(图片、视频、音频),需要使用
READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO等细分权限; - 对于非媒体文件,建议使用应用专属目录或存储访问框架(SAF)来操作。
4. 避免硬编码路径
不要直接使用/storage/emulated/0/com.domain.bundle这种硬编码路径,建议用path_provider提供的API获取合法路径,这样能适配不同设备的存储结构,也更符合Android的规范。
内容的提问来源于stack exchange,提问作者Kevin Walter
相关产品推荐
相关产品推荐

