如何在 Android 10、Target API 29 中从设备的共享存储(根目录)读取现有文件? [复制]

Posted

技术标签:

【中文标题】如何在 Android 10、Target API 29 中从设备的共享存储(根目录)读取现有文件? [复制]【英文标题】:How to read an existing file from device's shared storage(root directory) in Android 10, Target API 29? [duplicate] 【发布时间】:2020-04-15 08:45:24 【问题描述】:

我需要在第一次启动应用程序时读取存储在 android 根目录 (/storage/emulated/0/MyFolder) 中的文件。

使用Environment.getExternalStorageDirectory() 直到 API 级别 28 是可能的,但是在我迁移到 API 级别 29 后,Environment.getExternalStorageDirectory() 已弃用并停止使用以下消息。

此方法在 API 级别 29 中已弃用。为了改善用户隐私, 不推荐直接访问共享/外部存储设备。什么时候 一个应用程序以 Build.VERSION_CODES.Q 为目标,从这里返回的路径 应用程序不再可以直接访问方法。应用程序可以继续 通过迁移到访问存储在共享/外部存储上的内容 诸如 Context#getExternalFilesDir(String)、MediaStore、 或 Intent#ACTION_OPEN_DOCUMENT。

我还尝试了Context().getExternalFilesDir(null),它只返回以下路径“/storage/emulated/0/Android/data/com.myapp.appid/files/”,但我需要访问“/storage/”中的文件emulated/0/" 路径。

那么,在使用目标 API 级别 29 运行时,如何以合法方式读取位置“/storage/emulated/0/MyFolder”中的文件?

【问题讨论】:

不,我试过Context().getExternalFilesDir(null),但它返回的不是预期的应用程序私有文件路径。 Context().getExternalFilesDir(null) 仅返回以下路径“/storage/emulated/0/Android/data/com.myapp.appid/files/”,但我需要访问“/storage/”中的文件emulated/0/" 路径。 我不介意将此问题标记为重复,但认为此问题重复的人请完整阅读我的问题描述并标记重复。因为以下链接中提供的答案没有解决我的问题。 ***.com/questions/57116335/… need to read a file stored in android root directory(/storage/emulated/0/MyFolder)。但是谁在那里制作了那个文件夹?什么时候?谁在里面写了一个文件?什么时候? 您可以让用户使用 ACTION_OPEN_DOCUMENT 选择该文件。 【参考方案1】:

唯一的方法是要求用户选择带有Intent#ACTION_OPEN_DOCUMENT 的文件,然后用户不太可能选择该目录。

Google 声明进行此更改的目的是阻止应用程序在各处产生大量文件/文件夹,并让用户控制。您的应用程序私有目录之外的文件路径的概念不再存在,您必须使用 MediaStore 或 SAF(存储访问框架)来处理非私有内容。

今后,您将无法像这样拥有自己的应用程序的公共文件夹(除非在外部 SD 卡上),您只能将内容存储为视频、图像、音频或下载(所有其他文件类型)。

注意:目前 Android 10 之前的许多制造商提供了一个文档提供程序,可让您访问主分区的根目录以及外部 SD 卡,但如果您查看普通 Android 中提供的内容您不会看到为主根分区提供的操作系统模拟器图像或 Google 的文档,因为这会破坏 Google 对此更改的声明意图。

见https://developer.android.com/training/data-storage/

更具体的

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

您可以要求用户选择一个文件夹(该文件夹将位于受限制的公共位置下),然后您可以以编程方式访问和检查该位置中的文件。见https://developer.android.com/training/data-storage/shared/documents-files#grant-access-directory

您可以询问用户一次,然后使用https://developer.android.com/training/data-storage/shared/documents-files#persist-permissions 存储他们授予您访问文件/文件夹的权限

注意: 在 Android 11 之前有一个临时解决方法,方法是启用旧模式。

【讨论】:

所以没有办法以编程方式检查“/storage/emulated/0/”路径中是否存在文件? Google 声明此更改的目的是阻止应用程序在各处扩散文件/文件夹并让用户控制。您的应用程序私有目录之外的文件路径的概念不再存在,您必须使用 MediaStore 或 SAF(存储访问框架)来处理非私有内容。通过启用旧模式,在 Android 11 之前有一个临时解决方法。 You can ask the user to select a folder (which will be under the restricted public locations) 。不,完全没有限制。完全访问主分区。完全访问 micro SD 卡。在 SAF 中,“文件”和文件夹路径的概念保持不变。 Going forward you will not be able to have your own App's public folder。当然可以。每个应用程序都将使用 ACTION_OPEN_DOCUMENT_TREE。如果他想要的应用程序要求,用户不会拒绝选择主分区或 sd 卡。 虽然很多 Pre Android 10 手机制造商提供主分区文档提供程序,但您在 Emulator OS 映像或 Google 的文档中看不到这种类型的提供程序,我不希望这种做法继续(是的,如果您的手机支持 SD 卡,您将能够使用 SD 卡的根目录)

以上是关于如何在 Android 10、Target API 29 中从设备的共享存储(根目录)读取现有文件? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Android Target API - 如何测试我能走多低?

如何使用 Target API 23 及更高版本通过 GPS 获取用户位置

将图片保存到共享图片文件夹 android target api 29

Android 10 更新内容与适配

Android 10 更新内容与适配

Eclipse/Android:无法安装 Google API 目标