Search code examples
javaandroidandroid-11android-storagescoped-storage

Comprehensive data migration regarding Android 11 scoped storage and compatibility with versions < Android 10


Android 11 made almost all my apps obsolete because of the Scoped storage update! Okay, I will start by saying that:

Option #1 - android:requestLegacyExternalStorage="true" did not work for me even though I am still targeting sdk 29.

Option #2 - <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> also didn't work.

Doesn't really matter though, since option #1 would only work temporarily and option #2 would need to be justified when publishing to the store.

Now it leaves me with Option #3 - migrating all my data inside a scoped storage.

My app basically do 3 things:

  • Copy a folder named Test from the asset folder into the Environment.getExternalStorageDirectory() because I need a String path.

  • Generate an image and write it to Environment.getExternalStorageDirectory().

  • Reading that saved image from Environment.getExternalStorageDirectory().

Now my questions:

  1. Since I need a string path, I need to copy the folder named Test from the asset folder into the scoped storage? If so, how? Or is there another way?

  2. How do I save a bitmap to the scoped storage? Should I follow this tutorial: https://www.youtube.com/watch?v=tYQ8AO58Aj0

  3. How do I read the saved file from the scoped storage?

  4. If I do all the above adjustments, will they work for all Android versions? Or do I basically need to check the android version and use either Environment.getExternalStorageDirectory() for <10 and Scoped Storage for >= 10?


Solution

  • replace all Environment.getExternalStorageDirectory() occurences with getExternalFilesDir(subfolderNameInScopedStorage) - this need to be called on Context, so inside Activity, Service or you can obtain Context from e.g. Fragment by using getContext() method

    both methods are returning File, which is a directory for storing files (but they have different path ofc), so rest of your code won't change and should work

    getExternalFilesDir is in API since Android 4.4, so on older devices you may still use old getExternalStorageDirectory() method, just make an if in proper place - you should have one common (static?) method for obtaining main dir for storing files