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

Flutter中如何创建用户可在文件管理器查看的公共文件夹?

问题原因

你当前调用getExternalStorageDirectory()获取的是应用专属沙盒目录,Android 10及以上系统默认对该目录做了访问限制,仅你的应用自身可以读取写入,系统文件管理器、其他第三方应用都无法查看,且应用卸载时该目录会同步被删除,所以你在文件管理器里找不到对应文件夹。

解决步骤

1. 配置权限与适配属性

首先在你的安卓项目android/app/src/main/AndroidManifest.xml中添加以下配置:

<!-- 基础存储权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Android 13及以上专属媒体权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

<application
    ...
    <!-- 适配Android 10分区存储规则,必须添加 -->
    android:requestLegacyExternalStorage="true"
    ...>

2. 动态申请存储权限

存储权限属于Android危险权限,仅在清单文件声明无效,必须在运行时申请用户手动同意,推荐使用permission_handler包实现:

import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart';

Future<bool> checkAndRequestStoragePermission() async {
  if (Platform.isAndroid) {
    final androidInfo = await DeviceInfoPlugin().androidInfo;
    // Android 13及以上申请媒体权限
    if (androidInfo.version.sdkInt >= 33) {
      Map<Permission, PermissionStatus> status = await [
        Permission.photos,
        Permission.videos
      ].request();
      return status[Permission.photos]?.isGranted == true 
          && status[Permission.videos]?.isGranted == true;
    } 
    // Android 6.0-12申请通用存储权限
    else if (androidInfo.version.sdkInt >= 23) {
      PermissionStatus status = await Permission.storage.request();
      return status.isGranted;
    }
  }
  return true;
}

调用上述方法确认权限已授予后,再执行目录创建逻辑。

3. 创建公共可见目录

不要使用应用专属沙盒路径,改为在系统公共目录(如Pictures、DCIM、Documents等)下创建文件夹,推荐使用ext_storage包获取公共目录路径,避免硬写路径适配问题:

import 'package:ext_storage/ext_storage.dart';

// 先确认权限已授予
bool hasPermission = await checkAndRequestStoragePermission();
if (!hasPermission) return;

// 获取系统公共图片目录路径
String? publicPicturesPath = await ExtStorage.getExternalStoragePublicDirectory(
  ExtStorage.DIRECTORY_PICTURES
);
String targetDirPath = "$publicPicturesPath/bozzetto_camera";

// 创建目录
await Directory(targetDirPath).create(recursive: true).then((value) {
  print("创建成功,路径:${value.path}");
});

4. 通知媒体库刷新

目录/文件创建完成后需要主动通知系统媒体库扫描更新,否则文件管理器不会立即显示新创建的内容,可以使用gallery_saver等工具包在存文件时自动触发扫描,也可以手动调用系统广播实现刷新。

常见注意事项
  • 部分国产定制ROM(小米、华为、OPPO等)有额外的权限限制,若上述步骤执行后仍看不到目录,可手动进入系统设置-应用管理-你的应用-权限管理,确认「存储权限」或「访问所有文件」权限已开启
  • Android 11及以上系统无需申请所有文件访问权限,只要在公共媒体目录(Pictures/DCIM等)下操作,仅需媒体权限即可正常读写

内容的提问来源于stack exchange,提问作者Brutal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:57:03