如何在 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 获取用户位置