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

Android 11+下Flutter文件管理器的PathAccessException问题求助

问题背景

我用Flutter开发安卓文件管理器,核心功能是遍历整个文件系统,筛选mp3、mp4、pdf文件供用户查看。但在Android 11及以上版本中触发PathAccessException,无法访问/storage/emulated/0/Android/data这类目录,需要在遍历文件时排除Android文件夹。


文件检索方法

Future<List<File>?> getFiles() async {
    Directory dir = Directory("/storage/emulated/0");
    int totalSize = 0;
    List<File> files = [];

    if (dir.existsSync()) {
      List<FileSystemEntity> entities = dir.listSync(recursive: true);
      for (FileSystemEntity entity in entities) {
        if (entity is File) {
          File file = entity;
          String extension = file.path.split('.').last.toLowerCase();
          if (extension == 'mp3' || extension == 'mp4'  || extension == 'pdf') {
            int fileSizeInBytes = await file.length();
            totalSize += fileSizeInBytes;
            files.add(file);
          }
        }
      }

      print("Total size : $totalSize bytes");
      return files;
    } else {
      print("directory does not exist.");
      return null;
    }
  }

调用方式

List<File>? data = await provider.getFiles();
print(data);

异常信息

E/flutter ( 4188): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PathAccessException: Directory listing failed, path = '/storage/emulated/0/Android/data' (OS Error: Permission denied, errno = 13)
E/flutter ( 4188): #0      _Directory._fillWithDirectoryListing (dart:io-patch/directory_patch.dart:42:24)
E/flutter ( 4188): #1      _Directory.listSync (dart:io/directory_impl.dart:233:5)
E/flutter ( 4188): #2      FileManagerProvider.getFiles (package:filesharing/src/screens/file_manager/provider/file_manager_provider.dart:73:45)
E/flutter ( 4188): #3      _BottomTabsScreenState._getFiles (package:filesharing/src/screens/bottom_tabs/screens/bottom_tabs_screen.dart:49:39)
E/flutter ( 4188): #4      _BottomTabsScreenState._init (package:filesharing/src/screens/bottom_tabs/screens/bottom_tabs_screen.dart:30:5)
E/flutter ( 4188): <asynchronous suspension>

权限配置

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
    tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

同时已在AndroidManifest.xml的<application>标签中添加:

android:requestLegacyExternalStorage="true"

解决方案

不要直接使用listSync(recursive: true),改为手动递归遍历目录,遇到Android文件夹直接跳过。修改后的getFiles方法如下:

Future<List<File>?> getFiles() async {
  Directory rootDir = Directory("/storage/emulated/0");
  int totalSize = 0;
  List<File> files = [];

  if (!rootDir.existsSync()) {
    print("directory does not exist.");
    return null;
  }

  // 手动递归遍历目录
  void traverseDirectory(Directory dir) {
    try {
      List<FileSystemEntity> entities = dir.listSync();
      for (FileSystemEntity entity in entities) {
        // 排除Android文件夹
        if (entity is Directory && entity.path.endsWith('/Android')) {
          continue;
        }
        if (entity is File) {
          String extension = entity.path.split('.').last.toLowerCase();
          if (['mp3', 'mp4', 'pdf'].contains(extension)) {
            int fileSizeInBytes = entity.lengthSync();
            totalSize += fileSizeInBytes;
            files.add(entity);
          }
        } else if (entity is Directory) {
          traverseDirectory(entity);
        }
      }
    } catch (e) {
      // 捕获权限异常,跳过无法访问的目录
      print("无法访问目录: ${entity.path}, 错误: $e");
    }
  }

  traverseDirectory(rootDir);
  print("Total size : $totalSize bytes");
  return files;
}

关键修改说明

  • 移除recursive: true参数,改为手动递归遍历,避免强制访问受限目录
  • 检测到路径以/Android结尾的目录时直接跳过
  • 添加异常捕获,确保单个目录访问失败不会中断整个遍历流程
  • 将file.length()改为file.lengthSync(),避免异步嵌套导致的逻辑混乱

注意:即使拥有MANAGE_EXTERNAL_STORAGE权限,Android 11+系统也会限制对/Android/data、/Android/obb等目录的访问,因此必须主动排除这些目录才能避免权限异常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:17:46