You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:33:11