38

I want to store my document file into '/storage/emulated/0/Download/'. I got this error :

Unhandled Exception: FileSystemException: Cannot open file, path = '/storage/emulated/0/Download/file.pdf' (OS Error: Permission denied, errno = 13)

Here is my code:

void download() async {
  http.Response response = await http.post(url, headers: {"Accept": "application/json", HttpHeaders.authorizationHeader: 'Bearer'}});
    
  File file = new File('/storage/emulated/0/Download/file.pdf');
  await file.writeAsBytes(response.bodyBytes);
}
Ahmed Sbai
  • 10,695
  • 9
  • 19
  • 38
qing
  • 785
  • 1
  • 10
  • 24

11 Answers11

68

In Android Q, you need to add the Following Lines in AndroidManifest file:

 <application
      android:requestLegacyExternalStorage="true"
Rajil TL
  • 1,055
  • 1
  • 10
  • 7
  • 2
    is it related to the change of targetSdkVersion 29? – Leonardo Rignanese Dec 26 '20 at 16:05
  • 2
    Yes, make sense. If your `targetSdkVersion` is 28, don't need this line. If tour `targetSdkVersion` is 29 or more, need this line – Matias de Andrea May 15 '21 at 10:31
  • 2
    After adding this, if you get `error: attribute android:requestLegacyExternalStorage not found`, check [this answer](https://stackoverflow.com/a/59003853/3291390). Specifically, make sure you have `compileSdkVersion = 29` in android/app/build.gradle – Stack Underflow May 20 '21 at 19:24
28

Just add the following lines in to your android manifest if you're on android 10/Q

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
   <application
        android:requestLegacyExternalStorage="true"
    >
Charith Jayasanka
  • 4,033
  • 31
  • 42
24

I had the same problem

My solve:

use permission_handler

import 'package:permission_handler/permission_handler.dart';

before download action you need check storage permission:

var status = await Permission.storage.status;
                  if (!status.isGranted) {
                    await Permission.storage.request();
                  }

hope to help some body

Hưng Trịnh
  • 947
  • 1
  • 12
  • 23
16

Make sure you defined permissions in AndroidManifest file like this :

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxx.yyy">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
...
</manifest>

for more info try out this link

Aamil Silawat
  • 7,735
  • 3
  • 19
  • 37
  • 1
    thank you for your reply, I already put these permission but still have error – qing Mar 06 '20 at 06:26
  • @qing are you running this code in real device or emulator? – Aamil Silawat Mar 06 '20 at 06:27
  • run in real device – qing Mar 06 '20 at 06:28
  • 1
    So go to the setting/apps and check your application's permissions too in your real device – Aamil Silawat Mar 06 '20 at 06:30
  • did you check the attached link in my answer? – Aamil Silawat Mar 06 '20 at 06:35
  • after I refer the link I get the error > Minimum supported Gradle version is 5.4.1. Current version is 4.10.2. If using the gradle wrapper, try editing the distributionUrl in C:\flutter\.pub-cache\hosted\pub.dartlang.org\connectivity_macos-0.1.0+1\android\gradle\wrapper\gradle-wrapper.properties to gradle-5.4.1-all.zip BUILD FAILED in 2s The plugin connectivity_macos could not be built due to the issue above. – qing Mar 06 '20 at 09:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/209137/discussion-between-a-r-and-qing). – Aamil Silawat Mar 06 '20 at 09:31
5

In addition to Rajil TL's answer also include

targetSdkVersion 28

and stop process and run the app. Hot reload is not enough to reflect build.gradle changes.

Amal Paul
  • 201
  • 3
  • 5
3

In my cases none of the solutions worked, finally what worked was to remove from android/app/build.gradle the reference to "targetSdkVersion XX" inside defaultConfig{}

Now everything works as expected, I guess it is a bug in the framework.

Daniel
  • 1,007
  • 1
  • 11
  • 23
2

You have to add android:requestLegacyExternalStorage="true" this in AndroidManifest.xml file.

<application 
android:label="app_name"
        android:icon="@mipmap/ic_launcher"
        android:requestLegacyExternalStorage="true"
 </application>
1

Just change the targetSdkVersion to 28 from the build.gradle file. Rebuild app and run, it's working fine.

malware_656
  • 135
  • 5
  • 8
0

I faced this issue with a Galaxy S9. I couldn't use the last used pictures - I had to click on the gallery and photos tab in the top, the app asked for permission again, and then it worked.

PacifismPostMortem
  • 105
  • 1
  • 4
  • 9
0

My case was that it was possible to access directory. but couldn't read file.

final path= "${await ExternalPath.getExternalStoragePublicDirectory(ExternalPath.DIRECTORY_DOCUMENTS)}/sub";
final dir= Directory(path);
final l = dir.listSync(); // 1. works fine until here
for( final d in l){
   try{
      final  str = await File("${d.path}/info.json").readAsString(); // 2. permission error here
   }catch(e){
     print(e);
   }
}

for solving this problem, I included android.permission.MANAGE_EXTERNAL_STORAGE permission.

like belows.

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
     android:requestLegacyExternalStorage="true"
mika
  • 11
  • 1
0

After long Research i find this Solution and it will work on all Android 10+

Just change await Permission.storage.request() to await Permission.manageExternalStorage.request() in your Permission Handler or Requester class.

Because this change will give you full access to Media Storage excluding Restricted Storage.

Detail Example:

First Create a method.

Future<AppPermissionStatus> askForPhotoGalleryPermission(
  BuildContext context) async {
var status = Platform.isIOS
    ? await Permission.photos.request()
    : await Permission.manageExternalStorage.request(); 
AppPermissionStatus permissionStatus = AppPermissionStatus.NotAvailable;

if (status.isGranted) {
  permissionStatus = AppPermissionStatus.Granted;
  return permissionStatus;
} else if (status.isDenied) {
  permissionStatus = AppPermissionStatus.Denied;
  return permissionStatus;
} else if (status.isRestricted) {
  permissionStatus = AppPermissionStatus.Restricted;
  return permissionStatus;
} else if (status.isPermanentlyDenied) {
  permissionStatus = AppPermissionStatus.PermanentlyDenied;
}
return permissionStatus;
}

How to call this Method.

 void getRequiredPermission(BuildContext context) async {
 AppPermissionStatus permissionStatus =
    await AppPermission().askForPhotoGalleryPermission(context);
  setState(() {
  if (permissionStatus == AppPermissionStatus.Granted) {
    hasPermission = true;
  } else if (permissionStatus == AppPermissionStatus.PermanentlyDenied) {
    hasPermission = false;
  } else {
    hasPermission = false;
  }
});
}
Ramkesh Yadav
  • 987
  • 2
  • 11
  • 16