0

I am trying to write an Android App that, among other things, needs to read and write files to "external" storage.

While I am able to browse and select a folder on external storage, every time I try to access the file, I get a Permission denied I/O exception.

I HAVE included the following permissions in my app's manifest:

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

I have also enabled the STORAGE permission for the app in Android.

I am developing on a Chromebook, so I do not have access to emulators. So I test and debug my app on my phone (a Pixel 3), via a USB-C cable. I can also generate an APK and sideload it on my Chromebook, but I can not debug this way.

The following code sample was one I gathered from the Internet.

 public void writeFileExternalStorage(View view) {
        String cashback = "Get 2% cashback on all purchases from xyz \n Get 10% cashback on travel from dhhs shop";
        String state = Environment.getExternalStorageState();
        //external storage availability check
        if (!Environment.MEDIA_MOUNTED.equals(state)) {
            return;
        }
        File file = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOCUMENTS), filenameExternal);


        FileOutputStream outputStream = null;
        try {
            file.createNewFile();
            //second argument of FileOutputStream constructor indicates whether to append or create new file if one exists
            outputStream = new FileOutputStream(file, true);

            outputStream.write(cashback.getBytes());
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

When the file.createNewFile() is executed, The following exception is thrown: java.io.IOException: Permission denied

I have been banging my head against the wall for two days on this issue, and it's not doing any good. I hope someone here can help, as my head really hurts! :-)

Pfredd
  • 417
  • 6
  • 15
  • BTW - The value of "file" when the exception occurs is "/storage/emulated/0/Documents/cashbackFile" – Pfredd Jan 24 '20 at 20:20
  • Where do you [request the permissions at runtime](https://developer.android.com/training/permissions/requesting)? – ianhanniballake Jan 24 '20 at 20:25
  • I check for it at the beginning of the app. As specified in the Documentation you referred me to, I tested: ```if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)``` That testr is false, which should indicate that I have permission, correct? – Pfredd Jan 24 '20 at 20:47
  • Does this answer your question? [Storage permission error in Marshmallow](https://stackoverflow.com/questions/33162152/storage-permission-error-in-marshmallow) – Robin Jan 24 '20 at 20:51
  • I am doing that already, in earlier code. See my comment above. – Pfredd Jan 24 '20 at 20:57
  • Are you firm on the place the file needs to be stored? The common way, as documented in the [android developer documentation](https://developer.android.com/training/data-storage/app-specific), would be to use `getExternalFilesDir(...)` or use `MediaStorage` if the file needs to be accessible by other apps. – Kai Hatje Jan 24 '20 at 21:01
  • On Android Q you cannot write to getExternalStorageDirectory() anymore. – blackapps Jan 24 '20 at 21:08
  • getExternalFilesDir wont work as that is application owned file space that is removed when the app is uninstalled. – Pfredd Jan 24 '20 at 21:11
  • There HAS to be a way that my app can create a file that is outside of it's own private storage space. I don't really care where it is. I just need to be able to have an app's user download their data to their phone, then my app can access it and produce an output file that the user can access outside of my app. – Pfredd Jan 24 '20 at 21:16
  • OK - Maybe I am looking at this wrong. I can use the Android Adobe Lightroom app to save a photo to my phone. When I do this, it creates an "AdobeLightroom" directory in the root of the android filesystem, then stores the photo there. How is it able to do that? – Pfredd Jan 24 '20 at 21:30
  • That is probably done using the `MediaStore` API, as described in the [data-storage part of the developer documentation](https://developer.android.com/training/data-storage/). Unfortunately photos and such are treated differently from other documents, especially starting with Android 10. – Kai Hatje Jan 24 '20 at 21:59
  • I am going to ask this in a new question, as it deviates from my original post. – Pfredd Jan 24 '20 at 22:05

2 Answers2

5

Apparently, Android 10 is to blame.

I lowered the Target SDK to 28 (Android 9) and the code works.

It looks like if I want this to work for Android 10, I will have to use MediaStore for SDK 29+.

Pfredd
  • 417
  • 6
  • 15
0

you have to check for runtime permission before writeFileExternalStorage function :

private static final int WRITE_EXTERNAL_STORAGE = 0; private static final int REQUEST_PERMISSION = 0;

int permissionCheckStorage = ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    if (permissionCheckStorage != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE);
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                REQUEST_PERMISSION);

        return;
    }
mili2501
  • 452
  • 5
  • 9