58

I am targeting my Android app for Android 13 (API 33)

The WRITE_EXTERNAL_STORAGE permission seems to be working fine below API 33 i.e. Android 12 and less but the runtime permission popup for WRITE_EXTERNAL_STORAGE won't appear when running the app on Android 13.

My Android app creates one keystore file in app's private storage.

The behaviour changes for Android 13 mention this:

If your app targets Android 13, you must request one or more new permissions instead of the READ_EXTERNAL_STORAGE.

The new permissions are:

  • Images and photos: READ_MEDIA_IMAGES
  • Videos: READ_MEDIA_VIDEO Audio
  • Audio files: READ_MEDIA_AUDIO

I didn't find any information about this in the official documentation. The documentation is focusing on media files only without any word about other file types.

https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions

Rohit
  • 611
  • 1
  • 5
  • 7
  • 3
    `My Android app creates one keystore file in app's private storage.` For that not any permission is needed. – blackapps Sep 06 '22 at 11:08
  • And better read your link: `If your app targets Android 13 or higher and needs to access media files that other apps have created,` So if you want to create files on external storage you still should request write external storage permission. I dont know why there is no user interaction more. But more important: do you get write access for external storage (that is not app private)? – blackapps Sep 06 '22 at 11:13
  • The same. So my app got a huge bug because the scenario with create file checks permission and user can't go to next step – brucemax Oct 14 '22 at 23:39
  • Check this answer as it has some good points: https://stackoverflow.com/a/73630987/8929068 – Top4o Nov 02 '22 at 13:38

5 Answers5

45

TLDR: You don't.

From Google's official documentation:

"If your app targets Android 11, both the WRITE_EXTERNAL_STORAGE permission and the WRITE_MEDIA_STORAGE privileged permission no longer provide any additional access."

So in effect, if you were to request WRITE_EXTERNAL_STORAGE on Android 11 or later, you would be requesting nothing. This is the whole point of Android's migration to scoped storage, which effectively prevents apps from reading or writing to the storage directories of other apps UNLESS they are accessing specific file types (e.g. media, using the permissions you mentioned) or are granted special file manager permissions by Google themselves. For more insight into scoped storage, see this well written article, but TLDR security and leftover files from app uninstalls were the big reasons Google did this.

So if you really want to write files, either make sure you're only writing to your app's designated storage directories, in which case you won't need any permissions at all, or if you really need to write to a directory your app doesn't own get that file manager permission from Google (how to get that permission)

Hisham Hijjawi
  • 1,803
  • 2
  • 17
  • 27
  • 34
    Just to add, if you try to check or request the WRITE_EXTERNAL_STORAGE on Android 13+, it will always return false. So you'll have to skip the permission check/request completely on Android 13+. – Lifes Dec 11 '22 at 09:22
  • @HishamHijjawi I checked `ContextCompat.checkSelfPermission` with READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE. On A12 it returned true (at least after I called `requestPermissions` and accepted the storage permission request). But it returned false on A13 and there was no permission request popup for storage at all, when I called `requestPermissions` . I'm also using `requestLegacyExternalStorage`, but that should not affect this behavior because `requestLegacyExternalStorage` should be ignored completely since A11 versions. – JustAMartin Mar 28 '23 at 16:04
  • i need to create file but i got errro EACCES (Permission denied) – Muhammed shamshad p May 18 '23 at 11:11
  • But how about Media Store? Can it help to save a pdf file into the Downloads directory? – Waldmann Jun 17 '23 at 12:30
2

You can find documentation for accessing non-media files at Android official documentation or "How to Save a File in Shared Storage Location in Android 13". From Android 10 onwards, if you want to write a file which is intended to be accessible directly by other apps (such as File manager) or user, then you have to write it onto Shared Storage location. This has to be done in 3 steps:

Step 1: Launch System Picker to choose the destination by the user.

private ActivityResultLauncher<Intent> launcher; // Initialise this object in Activity.onCreate()
private Uri baseDocumentTreeUri;
public void launchBaseDirectoryPicker() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
        launcher.launch(intent);
 }

Step 2: Receive the chosen destination as Uri returned by System Picker in onActivityResult(). Here, you can optionally persist the permissions and Uri for future use.

@Override
    public void onActivityResult(ActivityResult result) {
        if (result.getResultCode() == Activity.RESULT_OK) {
            baseDocumentTreeUri = Objects.requireNonNull(result.getData()).getData();
            final int takeFlags = (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

            // take persistable Uri Permission for future use
            context.getContentResolver().takePersistableUriPermission(result.getData().getData(), takeFlags);
            SharedPreferences preferences = context.getSharedPreferences("com.example.fileutility", Context.MODE_PRIVATE);
            preferences.edit().putString("filestorageuri", result.getData().getData().toString()).apply();
        } else {
            Log.e("FileUtility", "Some Error Occurred : " + result);
        }
}

Step 3: Write content into a file.

public void writeFile(String fileName, String content)  {
        try {
            DocumentFile directory = DocumentFile.fromTreeUri(context, baseDocumentTreeUri);
            DocumentFile file = directory.createFile("text/*", fileName);
            ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(file.getUri(), "w");
            FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor());
            fos.write(content.getBytes());
            fos.close();
        } catch (IOException e) {
            
        }
}
Vivek Vashistha
  • 832
  • 9
  • 17
2

Use ( READ_MEDIA_IMAGES ) instead of ( WRITE_EXTERNAL_STORAGE ) If you are using sdk 33.

0

TO CHECK WRITE_EXTERNAL_STORAGE For Android API 31 and aove



    public static boolean isGrantedPermissionWRITE_EXTERNAL_STORAGE(Activity activity) {
        int version = Build.VERSION.SDK_INT;
        if( version <= 32 ) {
            boolean isAllowPermissionApi28 = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED ;
            Log.i("general_em","isGrantedPermissionWRITE_EXTERNAL_STORAGE() - isAllowPermissionApi28: " + isAllowPermissionApi28);
            return  isAllowPermissionApi28;
        } else {
            boolean isAllowPermissionApi33 = Environment.isExternalStorageManager();
            Log.i("general_em","isGrantedPermissionWRITE_EXTERNAL_STORAGE() - isAllowPermissionApi33: " + isAllowPermissionApi33);
            return isAllowPermissionApi33;
        }
    }

starball
  • 20,030
  • 7
  • 43
  • 238
Abdallah Mahmoud
  • 491
  • 1
  • 5
  • 8
-4

For Android 13 and above please use below permission,

<!-- Required only if your app needs to access images or photos
     that other apps created. -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

Please refer below referen

https://developer.android.com/training/data-storage/shared/media

Gowthaman M
  • 8,057
  • 8
  • 35
  • 54