82

I've been trying to encrypt files and write those files back on to the same place. But I got the error message saying "java.io.FileNotFoundException: /storage/emulated/0/New file.txt: open failed: EACCES (Permission denied)".

My Manifest file is this

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tdk.mytestapplication2">

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


<application
    android:allowBackup="true"

I think I have provided correct permission there. And the code I am using to encrypt files is this.

public static void encrypt(SecretKey secretKey, String filePath){
    try {
        // Here you read the cleartext.
        FileInputStream fis = new FileInputStream(filePath);
        // This stream write the encrypted text. This stream will be wrapped by another stream.
        FileOutputStream fos = new FileOutputStream(filePath);

        // Create cipher
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        // Wrap the output stream
        CipherOutputStream cos = new CipherOutputStream(fos, cipher);

        // Write bytes
        int b;
        byte[] d = new byte[8];
        while ((b = fis.read(d)) != -1) {
            cos.write(d, 0, b);
        }

        // Flush and close streams.
        cos.flush();
        cos.close();
        fis.close();

    }catch(IOException e){
        e.printStackTrace();
    }catch (NoSuchAlgorithmException e){
        e.printStackTrace();
    }catch(NoSuchPaddingException e){
        e.printStackTrace();
    }catch(InvalidKeyException e){
        e.printStackTrace();
    }
}

And I used this method inside a button

Button btnEncrypt = (Button) findViewById(R.id.btnEnc);
    btnEncrypt.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            aesKey = EncAndDec.generateKey();
            String filePath = editText.getText().toString();
            //Generating the file hash
            String md5Hash = MD5Hash.getMD5(filePath);

            System.out.println(aesKey.toString());
            System.out.println(filePath);
            System.out.println(md5Hash);

            //Encrypting the file
            for(int i=1; i<100; i++) {
                EncAndDec.encrypt(aesKey, filePath);
            }
        }
    });

Still I couldn't configure this error. Please someone help!

Boken
  • 4,825
  • 10
  • 32
  • 42
Tharindu
  • 963
  • 1
  • 7
  • 9
  • https://stackoverflow.com/questions/32635704/android-permission-doesnt-work-even-if-i-have-declared-it – CommonsWare Jun 14 '16 at 18:30
  • Please also confirm: does the file `/storage/emulated/0/New file.txt:` exist? Do you see it when you browse through your device? – ishmaelMakitla Jun 14 '16 at 18:34
  • @ishmaelMakitla hmmm since the message is "Permission Denied" then the file do exist(if it didn't the message would be "file not found") – niceman Jun 14 '16 at 18:36
  • The thing is your error includes `java.io.FileNotFoundException: /storage/emulated/0/New file.txt...`, hence I am asking if you have confirmed that the file does exist - in which case the error might be misleading. But things seem strange in your case, because you declared permissions yet you still get `Permission Denied` - so please cross check that the file itself is there. – ishmaelMakitla Jun 14 '16 at 18:41
  • @Tharindu What version of Android are you running? – Bryan Jun 14 '16 at 18:46
  • @Bryan my API is 23 Android 6.0 Marshmallow and now downgraded to 19 which is KITKAT – Tharindu Jun 14 '16 at 19:30
  • @ishmaelMakitla the file is there I can access it. – Tharindu Jun 14 '16 at 19:31

5 Answers5

140

If you are running in Android 29 then you have to use scoped storage or for now, you can bypass this issue by using:

android:requestLegacyExternalStorage="true"

in manifest in the application tag.

fabdurso
  • 2,366
  • 5
  • 29
  • 55
Prabhat Rai
  • 1,532
  • 2
  • 10
  • 12
  • 1
    You really saved me but I still having issues on android 5 – Islam Assem May 30 '20 at 22:46
  • I think you need to check your permissions @IslamAssem – Ahmed Shahid Jul 20 '20 at 10:53
  • 2
    can't believe they putted false by default... what a joke i spent 2 hours on it – Zhar Aug 30 '20 at 12:41
  • You made my day, thanks for this answer :-) – Raspberry Dec 06 '20 at 15:59
  • It's works but, is it a temporary solution? I already added manifest permissions and use in app permissions and still need legacy permission... It's feels wrong. – Mete Mar 14 '21 at 10:33
  • This is strange but after adding this line (along with runtime permission of WRITE_EXTERNAL_STORAGE) , now i am able to see ExternalRootDirectory path earlier it was coming as undefined, still when I open directory reader it shows 0 count, any suggestion ? look like , running with Android30 API same issue is with 29 – Dharmesh Apr 07 '21 at 14:39
  • @Dharmesh Did u add Read Permission? – Prabhat Rai May 06 '21 at 12:22
  • @Prabhat Rai Read + write_ext_storege both the permission are there – Dharmesh May 07 '21 at 05:56
  • 3
    This solution is temporary and won't work on Android 11. You have to use MediaStore class. Check this link for the permanent solution. https://sujeetkumargpt06.medium.com/storage-access-in-android-11-and-above-scoped-storage-8dc439e87441 – Sujeet May 14 '21 at 08:25
  • I worked for many hours, this is the only fix that worked. I never had an issue with saving file before. – Pete Mar 26 '22 at 21:05
60

I suspect you are running Android 6.0 Marshmallow (API 23) or later. If this is the case, you must implement runtime permissions before you try to read/write external storage.

Bryan
  • 14,756
  • 10
  • 70
  • 125
  • 3
    ... only if the target SDK is 23 or higher – devnull69 Jun 14 '16 at 18:54
  • 1
    My target SDK is 19 but emulator is 23 – Tharindu Jun 14 '16 at 19:27
  • @Tharindu Hm, as @devnull69 mentioned, if your `targetSdkVersion` is 22 or lower, then it should still use the old permissions model. This might not be the issue. – Bryan Jun 14 '16 at 19:31
  • @Bryan still installing some components right after installed them I'll give a try to run and update here – Tharindu Jun 14 '16 at 19:37
  • @Bryan do you have any samples for building runtime permissions I'm new to android development – Tharindu Jun 14 '16 at 19:38
  • @Tharindu The developer website has a pretty good [Runtime Permissions Sample](https://developer.android.com/samples/RuntimePermissions/project.html) application. – Bryan Jun 14 '16 at 19:53
  • @Bryan I have downgraded to android APK 19 KitKat and now its working fine. Thank you for the help – Tharindu Jun 14 '16 at 20:59
  • How about for instrumentation tests? Can we use **adb shell pm grant** [permission]? – IgorGanapolsky Mar 24 '17 at 19:59
  • @Tharindu, have you ever find a solution to this? If yes, you can post a separate answer for this. – Hemang Apr 23 '17 at 06:27
  • @Hemang The solution is as stated above; if your target SDK is level 23 or higher, you must implement runtime permissions. Otherwise, you only need to declare the permission in your `Manifest.xml` file – Bryan May 24 '17 at 18:57
24

Implement runtime permission for running your app on Android 6.0 Marshmallow (API 23) or later.

or you can manually enable the storage permission-

goto settings>apps> "your_app_name" >click on it >then click permissions> then enable the storage. Thats it.

But i suggest go the for first one which is, Implement runtime permissions in your code.

Debasish Mondal
  • 239
  • 4
  • 9
15

On Android 11, apps can no longer access files in any other app's dedicated, app-specific directory within external storage. To protect user privacy, on devices that run Android 11 or higher, the system further restricts your app's access to other apps' private directories.

Request MANAGE_EXTERNAL_STORAGE permission

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

Request External Storage Permissions

ActivityCompat.requestPermissions( this,
new String[]{
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.MANAGE_EXTERNAL_STORAGE
}, 1
);

Checking permission of MANAGE_EXTERNAL_STORAGE

// If you have access to the external storage, do whatever you need
if (Environment.isExternalStorageManager()){

// If you don't have access, launch a new activity to show the user the system's dialog
// to allow access to the external storage
}else{
  Intent intent = new Intent();
  intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
  Uri uri = Uri.fromParts("package", this.getPackageName(), null);
  intent.setData(uri);
  startActivity(intent);
}
sharsad k k
  • 171
  • 1
  • 10
2

For SDK 29 :

String str1 = "";
folder1 = new File(String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)));
if (folder1.exists()) {str1 = folder1.toString() + File.separator;}

public static void createTextFile(String sBody, String FileName, String Where) {
    try {
        File gpxfile = new File(Where, FileName);
        FileWriter writer = new FileWriter(gpxfile);
        writer.append(sBody);
        writer.flush();
        writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Then you can save your file like this :

createTextFile("This is Content","file.txt",str1);
yacine
  • 147
  • 1
  • 6