requestLegacyExternalStorage 在 Android 11 - API 30 中不工作

requestLegacyExternalStorage is not working in Android 11 - API 30

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

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

没错。 Android 11 (API 30+) requestLegacyExternalStorage=true 什么都不做,你不能再“opt-out”。它在 Android 10 中可用,为开发人员提供了 transition/grace 时间段,以便能够迁移到范围存储模型。

选项 1:在您的应用中迁移数据,同时仍以 API 29 为目标,然后一旦您迁移的数据与分区存储兼容,您应该能够发布一个以 API 30 为目标的更新- https://developer.android.com/training/data-storage/use-cases

如果用户跳过此版本并直接从以前的版本更新到最新版本并且您遇到无法访问的 un-migrated 数据,这可能会带来自己的问题。

选项 2:似乎 Google 看到了这个明显的警告,并在定位 API 30 时包含了一个 preserveLegacyExternalStorage=true 选项以允许您迁移数据。 https://developer.android.com/reference/android/R.attr#preserveLegacyExternalStorage

以后您可以参考此 table 来根据 use-case 决定使用什么存储“框架”:https://developer.android.com/training/data-storage

有些应用可能无法成功迁移,这取决于它们与 File API 的交互方式,因为 Google 的解决方案不会包含所有当前 use-case 并且可能没有迁移路径。

例如,几年前我发布了一个应用程序,允许用户使用 MediaStoreContentResolver 来更新专辑插图以更新专辑插图图像的数据 - 这存储在共享存储。查看 Android 10+ AOSP MediaProvider 源代码后,似乎过去使用 MediaStore 更新专辑封面以指向数据文件的应用程序不再有效,仅仅是因为 MediaProvider 在隐藏的 .thumbnails 文件夹中直接查看 mp3 并使用 MediaExtractor 在内部创建自己的作品,并且从不引用插入以引用作品的 ContentValues。因此,即使您可以自己更新艺术品,查询 MediaStore 并查看它,其他应用程序也必须使用 ContentResolver#loadThumbnail in API 29+ 不引用您的更新值,并且懒惰地创建一个艺术作品,或者在 .thumbnails 文件夹中选择已经生成的文件。显然,其中 none 已记录在案,我的应用程序受到负面评论的强烈反对,但这些更改是破坏性更改,完全超出了我的控制范围,因此我查看了 AOSP 源代码,发现 Android 从根本上改变了行为。

(这不是咆哮,而是这些更改如何由于 AOSP 的基本未记录行为而没有提供迁移路径的示例)。

https://developer.android.com/about/versions/11/privacy/storage 所述,Android 11 上的存储有一些变化:

  • Android 10 台设备
    • requestLegacyExternalStorage 将继续工作,无论目标 sdk
  • Android 11 台设备
    • 针对 sdk 29 的新安装:requestLegacyExternalStorage 值得到尊重
    • 针对 sdk 30 的新安装:requestLegacyExternalStorage 始终是 false
    • 从目标 sdk 29 升级到 30:如果设置了 preserveLegacyExternalStorage,那么 requestLegacyExternalStorage 就是 true(这是纯粹的迁移案例,如果用户 uninstall/reinstall 应用)

此时您几乎被迫实施分区存储。除非您准备好迁移,否则请继续以 sdk 29 为目标,因为无法在目标 sdk 30 的 Android 11 台设备上强制执行旧存储。

更新:截至 2021 年 8 月,Play 商店需要目标 SDK 30

2021 年初之前不要这样做(google 说):-

如果你想定位到 android 11,你应该使用 MANAGE_EXTERNAL_STORAGE 权限。

访问此页面了解更多详情:https://developer.android.com/training/data-storage/manage-all-files

运行 Android 11 但目标 Android 10(API 级别 29)的应用程序仍然可以请求 requestLegacyExternalStorage 属性。此标志允许应用程序暂时选择退出与范围存储相关的更改,例如授予对不同目录和不同类型媒体文件的访问权限。 将应用程序更新到目标 Android 11 后,系统忽略 requestLegacyExternalStorage 标志。

无需调用不适用于 Android 11+ 的“requestLegacyExternalStorage=true”。

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