Faced same issue recently when I tried listing all directories and sub-directories from my android phone and got same error.
Unhandled Exception: PathAccessException: Directory listing failed, path = '/storage/emulated/0/Android/data' (OS Error: Permission denied, errno = 13)
Noticed this only happens on android version 11 and above. With google latest policy of not allowing an app to read other apps data which is inside the Android folder.
I achieved this with below code.
Do not forget to add this permission in your androidManifest
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
Then request permission before accessing files
var status = await Permission.manageExternalStorage.request();
//status = await Permission.storage.request();
if (status.isGranted == true) {
} else {
}
First
declare a function with your preferred directory,
List all parent folders first by passing false to listSync recursive argument
Future getAllDir() async {
Directory dir = Directory('/storage/emulated/0');
List<FileSystemEntity> entries = dir.listSync(recursive: false).toList();
}
If recursive is true, sub directories will be listed and for android version 11 and above, this will throw the above error.
Now you can further filter the list and remove any directory that mathches with the android folder or directory
Future getAllDir() async {
Directory dir = Directory('/storage/emulated/0');
List<FileSystemEntity> entries = dir.listSync(recursive: false).toList();
entries.removeWhere(
(element) => element.path == "/storage/emulated/0/Android");
log("Directories $entries");
}
Okay , now you can do anything you wish to do with the filtered list of FileSystemEntity
Example :
You can further run a for loop operation on the filtered list
and for each of the FileSystemEntity , you can pass a new directory with the the FileSystemEntity path.
The below operation list all pdf files from your device from all directories excluding the android folder / directory
Future getAllDir() async {
Directory dir = Directory('/storage/emulated/0');
List<FileSystemEntity> entries = dir.listSync(recursive: false).toList();
entries.removeWhere(
(element) => element.path == "/storage/emulated/0/Android");
log("Directories $entries");
for (FileSystemEntity entity in entries) {
// new directory for each of the entries
Directory newdir = Directory(entity.path);
// inner for loop operation to list all directories and sub directories for each entry
// and you have to pass true to recursive argument
await for (FileSystemEntity newEntity in newdir.list(recursive: true, followLinks: false)) {
if (newEntity.path.endsWith('.pdf')) {
log("PDF Files ${newEntity.path}");
} else {
log("No Files ");
}
}
}
}