47

Google has introduced some changes recently related to storage APIs in API 29 like scoped storage and we opted out by adding 'requestLegacyExternalStorage=true' in Manifest. But now when I targetSdkVersion 30, this no longer seems to work. Some of the files in the download directories were not listing (File.listFiles) after this change.

Abhishek Kumar
  • 4,532
  • 5
  • 31
  • 53
Ebin Joy
  • 2,690
  • 5
  • 26
  • 39

5 Answers5

59

But now when I targetSdkVersion 30, this no longer seems to work

That is correct. Android 11 (API 30+) requestLegacyExternalStorage=true does nothing and you can no longer "opt-out". It was available in Android 10 to give developers a transition/grace period to be able to migrate to the scoped storage model.

Option 1: Migrate data in your app whilst still targeting API 29, then once you're migrated data is compatible with scoped storage you should be able to release an update targetting API 30 - https://developer.android.com/training/data-storage/use-cases

This can come with its own problems if users skip this version and updates directly from a previous version to the latest and you're stuck with un-migrated data you can't access.

Option 2: It seems that Google sees this obvious caveat and has included a preserveLegacyExternalStorage=true option when targetting API 30 to allow you to migrate data. https://developer.android.com/reference/android/R.attr#preserveLegacyExternalStorage

Going forward you can reference this table for deciding what storage "framework" to use based on the use-case: https://developer.android.com/training/data-storage

There is a potential that some apps simply won't be able to successfully migrate, based on how they interacted with the File API as Google's solution will not encompass all current use-cases and there might not be a migration path.

For instance, I released an app a couple of years ago that allowed users to update album artwork using MediaStore and ContentResolver to update the data for the album artwork image - this was stored in shared storage. Having looked at the Android 10+ AOSP MediaProvider source code it seems that apps that used to use MediaStore to update album artwork to point to a data file no longer works, simply because the MediaProvider internally creates its own artwork in a hidden .thumbnails folder looking directly at the mp3's and using a MediaExtractor, and never references the ContentValues that were inserted to reference the artwork. So even though you can update the artwork yourself, query the MediaStore for it and see it, other apps have to use ContentResolver#loadThumbnail in API 29+ that does not reference your updated values and either creates an artwork lazily, or picks the already generated file in the .thumbnails folder. Obviously, none of this is documented, and I got a massive backlash to my app with negative reviews, yet these changes were breaking changes and completely out of my control and took me looking through AOSP source code to find that Android had fundamentally changed behaviour.

(This wasn't a rant, but an example of how these changes offered no migration path because of fundamental undocumented behaviour to AOSP).

Adinia
  • 3,722
  • 5
  • 40
  • 58
Mark
  • 9,604
  • 5
  • 36
  • 64
  • 2
    What about the Android versions below SKD 29? How to deal with permissions? My App supports SDKs 21+. I still need to consider permissions for those versions. Thanks! – Mark Delphi Jan 13 '21 at 16:16
  • I have application targeting 29 in playstore. Do i need to release new version immediately on playstore befor 5th may? Or i can wait for my next release? – user3066829 Apr 16 '21 at 22:52
  • No - you only need to do this if you target 30 - "This is only applicable to apps that target Android 11 (API level 30) and declare the MANAGE_EXTERNAL_STORAGE permission, which is added in Android 11" - https://support.google.com/googleplay/android-developer/answer/10467955 - no doubt this will be a temporary reprieve and Google might decide somepoint in the future all new apps and releases target 30+. Basically you should have a migration strategy in place when you target api 30 .. I'd be surprised, unless you're a big player in the app sphere that you'll be an easy pass for the permission. – Mark Apr 16 '21 at 23:31
  • see below update from @Pawel - "update: play store will require target sdk 30 as of August 2021" – Mark Apr 16 '21 at 23:44
  • @MarkKeen Would you please take a look into: https://stackoverflow.com/questions/63364476/requestlegacyexternalstorage-is-not-working-in-android-11-api-30#comment118831398_63365334 – Dr.jacky Apr 23 '21 at 10:52
  • And I thought Apple was bad for developers :eye-roll: – Dale_Plante May 22 '23 at 10:51
41

As stated in https://developer.android.com/about/versions/11/privacy/storage there are some changes regarding storage on Android 11:

  • Android 10 devices
    • requestLegacyExternalStorage will continue to work regardless of target sdk
  • Android 11 devices
    • new installation targetting sdk 29: requestLegacyExternalStorage value is respected
    • new installation targetting sdk 30: requestLegacyExternalStorage is always false
    • upgrade from targetting sdk 29 to 30: if preserveLegacyExternalStorage is set then requestLegacyExternalStorage is true (this is pure migration case and this state won't be preserved should user uninstall/reinstall the app)

You're pretty much forced to implement scoped storage at this point. Unless you're ready to migrate just keep targetting sdk 29 as there's no way to enforce legacy storage on Android 11 devices with target sdk 30.

update: play store requires target sdk 30 as of August 2021

Pawel
  • 15,548
  • 3
  • 36
  • 36
  • 1
    any tutorial about step for doing that, please? – Moustafa EL-Saghier Jan 25 '21 at 21:44
  • 2
    I have searched for 6 hours, but at last found the clear concept, thanks, But, is there any tutorial that show migrating and supports all api regardless ? – Noor Hossain Feb 15 '21 at 19:51
  • Did you test the "upgrade from targetting sdk 29 to 30" case. I have tried several time. But accessing to legacy storage is always failed whether target from 28 to 30 or from 29 to 30. – opLW Feb 20 '21 at 08:15
  • @opLW I have no issue with installation upgrade on API 30 emulator. – Pawel Feb 20 '21 at 11:38
  • Oh, sorry. I miss something. Now I get the case right. – opLW Feb 22 '21 at 01:14
  • "update: play store will require target sdk 30 as of August 2021" - that refactor you've been putting off just got a deadline ... – Mark Apr 16 '21 at 23:43
  • 1
    @Pawel I migrated my code to the new solution for Android API 30 and it works on Emulator API 30 but still, picking an image from the gallery doesn't work on Emulator API 29!; The targetSDK is 30; But, if I add `requestLegacyExternalStorage = true` while I'm following that new solution (MediaStore - API 30), it works on every API version. Is that what should we do? – Dr.jacky Apr 23 '21 at 10:50
  • @Dr.jacky sorry but I can't advocate for google on how they're going to execute their store policies. If you have issues with scoped storage implementation open up a new question. – Pawel Apr 23 '21 at 11:29
  • @Pawel on my app preserveLegacyExternalStorage = true . ı have installed on android device after that update system to android 11 but externalstorageLegacy is false why? – ahmetvefa53 Nov 09 '21 at 11:48
  • For my case, run Android 11 is good with permission of:MANAGE_EXTERNAL_STORAGE, but when run on Android 10 or bellow, I can list the media files such as jpg file, but no other files will be shown? I'm completely blocked. – Jianwu Chen Mar 06 '22 at 23:27
4

Don't do this until early 2021 (said by google):-

If you want to target to android 11, you should use the MANAGE_EXTERNAL_STORAGE permission.

Visit this page for more details: https://developer.android.com/training/data-storage/manage-all-files

Rituraj Shakti
  • 425
  • 6
  • 4
  • 13
    This comes with a big caveat, the app must conform to the Google Play policy for this permission, " the app’s usage of the permission must fall within permitted uses, and must be directly tied to the core functionality of the app" - so unless your app is a File Manager or Virus scanning app etc.. I'd advise not to use this permission, otherwise you might find its rejected and have a load of refactoring to do. – Mark Dec 26 '20 at 21:59
  • @MarkKeen any solution for this problem? – RkKhanpuriya Nov 28 '21 at 16:31
  • I applied for this permission. And get approved. my application is an eBook reader. But the problem is now my app only works for android 11+. For the older version, there's no way to get MANAGE_EXTERNAL_STORAGE permission. – Jianwu Chen Mar 06 '22 at 23:31
1

Applications that run on Android 11 but target Android 10 (API level 29) can still request the requestLegacyExternalStorage attribute. This flag allows applications to temporarily opt out of the changes associated with scoped storage, such as granting access to different directories and different types of media files. After updating application to target Android 11, the system ignores the requestLegacyExternalStorage flag.

Ajay Prajapati
  • 668
  • 1
  • 10
  • 18
-1

No need to call "requestLegacyExternalStorage=true" which is not working for Android 11+.

There is a new update in https://github.com/apache/cordova-plugin-media to cover the saving file path issue for android 11+.

If you update "/platforms/android/app/src/main/java/org/apache/cordova/media/AudioHandler.java" and "/platforms/android/app/src/main/java/org/apache/cordova/media/AudioPlayer.java" in your project, then it should be working.

https://raw.githubusercontent.com/apache/cordova-plugin-media/4093f7e14fe65f94ffbef072ed188a0205e78a59/src/android/AudioHandler.java

https://raw.githubusercontent.com/apache/cordova-plugin-media/4093f7e14fe65f94ffbef072ed188a0205e78a59/src/android/AudioPlayer.java

Hesam
  • 24
  • 3