requestLegacyExternalStorage在Android 11 – API 30中无法使用。

huangapple go评论145阅读模式
英文:

requestLegacyExternalStorage is not working in Android 11 - API 30

问题

Google最近在API 29中引入了一些与存储API相关的更改,如作用域存储,并且我们通过在清单中添加'requestLegacyExternalStorage=true'来选择退出。但是现在,当我将targetSdkVersion升级到30时,似乎这不再起作用。在此更改后,下载目录中的某些文件未列出(File.listFiles)。

英文:

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.

答案1

得分: 59

"But now when I targetSdkVersion 30, this no longer seems to work"
"但现在当我将targetSdkVersion设置为30时,这似乎不再起作用"

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.
这是正确的。Android 11(API 30+)中的requestLegacyExternalStorage=true不再起作用,您不能再选择“opt-out”。它在Android 10中可用,以便为开发者提供过渡/宽限期,以便能够迁移到作用域存储模型。

Option 1: Migrate data in your app whilst still targeting API 29, then once your migrated data is compatible with scoped storage you should be able to release an update targeting API 30 - https://developer.android.com/training/data-storage/use-cases
选项1:在仍然以API 29为目标的情况下迁移您应用中的数据,一旦您的迁移数据与作用域存储兼容,您就应该能够发布一个针对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 targeting API 30 to allow you to migrate data. https://developer.android.com/reference/android/R.attr#preserveLegacyExternalStorage
选项2:看起来Google看到了这个明显的注意事项,并在目标API 30时包含了一个preserveLegacyExternalStorage=true选项,允许您迁移数据。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
今后,您可以参考这个表格来决定根据用例选择使用哪种存储“框架”: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.
有可能一些应用程序根本无法成功迁移,这取决于它们与File API 的交互方式,因为Google的解决方案不会涵盖所有当前的用例,可能没有迁移路径。

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 behavior.
例如,我几年前发布了一个应用程序,允许用户使用MediaStoreContentResolver更新专辑封面,以更新专辑封面图像的数据 - 这些数据存储在共享存储中。查看了Android 10+ AOSP的MediaProvider源代码后,似乎以前使用MediaStore来更新专辑封面以指向数据文件的应用程序不再起作用,仅仅因为MediaProvider在隐藏的.thumbnails文件夹中内部创建自己的封面,直接查看mp3文件并使用MediaExtractor,并且从未引用插入的ContentValues来引用封面。因此,尽管您可以自己更新封面,查询MediaStore并查看它,但其他应用程序必须在API 29+中使用ContentResolver#loadThumbnail,它不引用您的更新值,要么懒惰地创建封面,要么选择已在.thumbnails文件夹中生成的文件。显然,所有这些都没有记录下来,我收到了我的应用程序的大量负面评价,尽管这些更改是重大更改,完全超出了我的控制,并迫使我查看AOSP源代码以发现Android已经从根本上改变了行为。

英文:

> 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).

答案2

得分: 41

请注意以下关于Android 11存储的更改:

  • Android 10设备
    • requestLegacyExternalStorage 将继续工作,无论目标SDK是什么。
  • Android 11设备
    • 新的安装目标SDK 29:requestLegacyExternalStorage 的值会被尊重。
    • 新的安装目标SDK 30:requestLegacyExternalStorage 总是为 false
    • 从目标SDK 29 升级到 30:如果设置了 preserveLegacyExternalStorage,则 requestLegacyExternalStoragetrue(这仅是迁移情况,如果用户卸载/重新安装应用程序,此状态将不会被保留)。

在这一点上,您几乎被迫实施作用域存储。除非您准备好进行迁移,否则只需继续使用目标SDK 29,因为无法强制在目标SDK 30上使用旧存储在Android 11设备上。

更新:自2021年8月起,Play商店要求使用目标SDK 30

英文:

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

答案3

得分: 4

如果您想针对Android 11进行目标定位,应该使用MANAGE_EXTERNAL_STORAGE权限。

访问此页面获取更多详细信息:https://developer.android.com/training/data-storage/manage-all-files

英文:

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

答案4

得分: 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.

英文:

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.

答案5

得分: -1

不需要调用 "requestLegacyExternalStorage=true",这对于 Android 11+ 不起作用。

https://github.com/apache/cordova-plugin-media 中有一个新的更新,用于解决 Android 11+ 的文件保存路径问题。

如果您在项目中更新 "/platforms/android/app/src/main/java/org/apache/cordova/media/AudioHandler.java" 和 "/platforms/android/app/src/main/java/org/apache/cordova/media/AudioPlayer.java",那么它应该可以工作。

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

英文:

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

huangapple
  • 本文由 发表于 2020年8月12日 02:43:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63364476.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定