问题标签 [scoped-storage]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 使用 Android 的 MediaStore(ContentResolver/范围存储)创建图像文件后文件扩展名和文件名错误
我正在使用MediaStore 和 ContentResolver API 来保存使用MediaStore.Images
. 它可以工作,但问题是所有文件都以 .jpg 扩展名保存,并且文件名始终是"the current time in millis.jpg"。
这是我在 ContentValues 中放入的示例:
但是在将其插入 ContentResolver 并写入文件后,显示名称更改为2067623.jpg
,文件名称更改为1575480356.jpg
.
我如何让它保留文件名和扩展名?
代码:
android - Android Q,如何使用正确的文件名使用 MediaStore 保存录音?
我想将使用我的应用程序录制的 mp3 文件存储到带有 MediaStore 的 Music 文件夹中,用于 Android 10 的新“范围存储”。
这种方法效果很好,但文件以时间戳命名(例如 1576253519449),没有.mp3
扩展名。
如果我使用文件管理器手动添加扩展名,则文件被正确记录。
我如何使用fileName + ".mp3"
来命名文件?
还有一个问题:MediaStore.Audio.Media.RELATIVE_PATH
仅适用于 Android 10。如何保持与旧版本的追溯兼容性?
编辑:
为了追溯兼容性,您可以删除values.put(MediaStore.Audio.Media.RELATIVE_PATH, "Music/Recordings/");
:文件将直接保存在 Music 目录中。
或者使用if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
仅在 Android 10 上添加子目录。
android - 如何使用范围存储创建外部目录并授予对目录 android 的访问权限
在我的应用程序中,我需要创建一个外部目录并将文档文件存储在子目录中。截至 Android Pie,API 28 它进展顺利。从 Android 10 开始,它已经发生了变化,并且在范围存储中,我如何在外部存储中创建目录并授予对整个目录的权限?我想使用 uri 将文件下载到这些目录,我想稍后使用它们的 uri 阅读它们。
android - 从 RELATIVE_PATH + DISPLAY_NAME 获取媒体的 URI 或 ID
我正在尝试简单地添加音频文件。我的解决方案大多有效。但是当文件已经存在于MediaStore
. 我仔细查看过的一次也只存在于MediaStore
该位置的设备上没有文件。
尝试插入该新文件时,Logcat 会输出以下内容。
这files._data
意味着该文件已经存在于MediaStore
. 没有文件JDrop/1/1/12.mp3
,它只是在MediaStore
,我需要以某种方式摆脱它或为现有MediaStore
条目获取一个 OutputStream 并相应地更新它。
我尝试使用以下代码查询ID
in没有成功。MediaStore
要么找出 要么ID
会URI
很好。此外MediaStore.Audio.Media.DATA
,自 SDK 29 起已弃用。所以我想在不使用它的情况下查询它。
编辑 1(查询 _data)
我现在还尝试_data
使用我知道无法插入的硬编码路径进行查询,但没有取得多大成功。
也返回 null 并返回 false。
编辑 2(查询所有内容并查看它返回的内容)
我尝试按照建议对整个集合进行一些测试查询。
它返回一个包含 2557 个条目的列表。作为第一个示例,名称是"5.mp3"
id 是79658
相对路径"Music/JDrop/1/1"
。前面有一个Music/
我不知道的。但 find12 仍然为空。
编辑 3(可能重要或不重要的其他想法)
还可能值得注意的是,它不会发生在我使用 android 10 创建的 Android 模拟器上。但它会发生在我的 OnePlus 6 上,其中包含大约 300 多个文件,并且适用于所有其余部分。我已经在 Android 9 中使用该程序,然后升级到 Android 10。我在某处读到,当您升级到 10 时,来自 Android 9 的文件可能被认为是孤立的,而不是属于您的应用程序(至少当您卸载创建它们的应用程序)。所以我可能无法再访问我正在寻找的媒体商店条目?不过,我也想过。现在无需任何许可,任何应用程序都可以访问阅读媒体。因此,如果这是一个访问问题,则在尝试写入时应该会失败。不是在阅读或找到它时。
此外,正如@CommonsWare 提到的那样,IS_PENDING
可能仍设置为1
. 我确实将其设置回0
我发布的代码下方。但是,每当我在调试时关闭程序时,该代码可能永远不会执行,因为它将在下载和写入文件的部分进行 9/10 次,因为这是迄今为止程序中发生的任何事情的最长时间。
android-external-storage - 如何在 Android 10 中从卸载持久内存中写入/读取文本文件
我希望我的应用程序将文本文件写入 Documents 文件夹(或卸载应用程序后仍然存在的任何其他内存部分)。
在 Android 9 (SDK 28) 之前,可以按如下方式访问 Documents 文件夹
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
由于新的范围内存策略,现在已弃用。官方文档说
通过迁移到 Context#getExternalFilesDir(String)、MediaStore 或 Intent#ACTION_OPEN_DOCUMENT 等替代方案,应用程序可以继续访问存储在共享/外部存储上的内容。
第一个选项,Context#getExternalFilesDir(String)
不是我想要的,因为
这就像 getFilesDir() 一样,在卸载应用程序时这些文件将被删除
第三个选项Intent#ACTION_OPEN_DOCUMENT
是不够的,因为我想在访问之前写入文件。
看起来MediaStore
是唯一的办法。我在 MediaStore 中看到了一些不完整的代码示例,但我找不到详尽的答案。
请问,您能否提供一个完整的 Java 片段,展示如何在 Android 10 中从卸载持久内存中写入/读取文本文件?尽管 Android 10 有严格的隐私政策,但如果用户授予权限,我不明白为什么这是不可能的。非常感谢。
android - 将文件写入 Android Q 中可公开访问的文档文件夹 - Scoped Storage
背景
迁移到 Android 后,QI 无法再找到合适的方法来获得对文档文件夹的写入权限 ( /storage/emulated/0/Documents
)
在任何人提到有关范围存储的许多其他问题之前,我已经阅读了其中的许多问题,并且到目前为止我所看到的所有解决方案都使用特定于应用程序的目录或仅访问媒体目录(而不是文档文件夹访问)。
根据我对 Android QI 的了解,可以选择:
- 使用只能由我的应用程序(或我授予权限的应用程序)访问的应用程序特定目录
- 允许用户选择他们想要存储文件的位置(我认为这可以是公共位置)
ACTION_OPEN_DOCUMENT_TREE
问题
我开发的应用程序用于对主题进行测试,测试中的数据自动存储在可公开访问的 Documents 文件夹中,有点像:/storage/emulated/0/Documents/myAppName/subjectName/testData-todaysDate.pdf
当用户想要访问测试数据时,他们将智能手机插入计算机并导航到文档文件夹,剩下的就很明显了。出于这个原因,我必须使用可公开访问的存储。还可以想象他们想通过另一个应用程序在手机上打开测试数据,同样的交易!
我正在寻找的解决方案
因此,我正在寻找的解决方案需要能够执行以下操作:
- 不多次请求许可(一次即可)
- 无需用户提示自动保存测试数据(因为将进行数百次测试)
- 保存到公共文档文件夹,例如
/storage/emulated/0/Documents/
- 不涉及用户选择目录,所以不
ACTION_OPEN_DOCUMENT_TREE
- 理想情况下,数据是持久的,因此卸载应用程序不会导致数据丢失
我知道 Android Q 中的这些变化是为了让用户更多地“了解”应用程序如何访问他们的数据,但是一旦他们了解您的应用程序如何使用您的数据,就不会有问题了。
android - 如何使下载的文件在 Android Q 的图库中可见?
我正在使用下载管理器下载文件,如下所示:
下载后,我将其添加到媒体商店,如下所示:
我将看到在图库中创建的文件夹,但该文件始终显示为已损坏。任何人都可以帮忙吗?
java - 如何从 Document Uri 获取孩子的 DocumentFile
假设以下文件夹结构:
鉴于下面列出的 Uri,如何获取位于/Test/Example
路径中的目录的 DocumentFile,其中 Test 和 Example 是动态选择的目录?
我需要 /Test/Example 目录的 DocumentFile,因为我需要进一步遍历树并查找/检查是否存在其他目录,例如/Test/Example/Dir1/Dir2/test.txt
,但在运行时我不知道目录的名称是什么。
android - 如何通过 DocumentContract.moveDocument() 将 mediastore 内容项移动到另一个目录?
由于 Android 通过范围存储访问强制使用存储访问框架,因此应用程序无法使用直接 java.io.file 操作来移动文件。
目的是将某些从 mediastore 数据库中查询到的特定媒体项移动到另一个特定目录(源文件的同一分区),该目录用户已授予应用程序 rw 权限。
但是,当我尝试使用方法创建 DocumentFile 实例时
在这种情况下,创建的实例的父 DocumentFile 为 null。以及方法
需要源父级移动文档文件。我知道我可以通过读/写 IO 流将源复制到目标,但这并不有效。那么,我怎样才能以推荐的方式做到这一点呢?
另一个问题是,如果有办法将内容从 mediastore 移动到另一个地方,如何在不删除底层文件实体的情况下将其从数据库中删除?
android - Android 10:如何以编程方式删除 MediaStore 项目及其在文件系统上的关联数据?
我正在更新我的应用程序以使用 Android 10 中引入的 Scoped Storage 功能。
我的应用程序与 MediaStore 一起使用并显示图像、视频和音频文件,并为用户提供删除项目的能力。
我之前为删除文件所做的操作:
- 从那里得到路径
MediaStore.MediaColumns.DATA
- 用于
new File(path).delete()
删除该文件 - 手动更新 MediaStore
现在 MediaStore.MediaColumns.DATA 不可用我迁移到使用ContentResolver.delete()从 MediaStore 中删除项目
例如,我有项目的 uri:(content://media/external/images/media/502
它的有效 uri,我在网格中显示它的缩略图)。我是否在 MediaStore 或其他应用程序中插入了这个项目并不重要。
我用context.getContentResolver().delete(uri, null, null)
. 它要么成功删除(返回 1 行),要么捕获RecoverableSecurityException
用于startIntentSenderForResult()
访问当前 uri,然后使用相同的 uri 将getContentResolver().delete()
其删除,onActivityResult()
然后成功删除。
无论哪种方式,该项目都会从 MediaStore 中删除,并且在我查询 MediaStore 以获取图像时或在其他应用程序中都不会显示在结果中。
但此文件存在于文件系统上(使用 SAF 和各种文件管理器(Google Files、Total Commander)检查)
有时(取决于 Android 版本和媒体类型)这些项目会在手机重新启动后(或打开 Google 相册后 - 它会扫描文件系统)带回 MediaStore
例如:我的 Google Pixel 和 Google Pixel 3a XL 上的 Android 10 的行为与上述图像/视频/音频的行为相同,但小米 Mi A2 Lite 上的 Android 9 仅对音频文件的行为如此,而删除图像/视频则很好。
我有android:requestLegacyExternalStorage="false"
清单。
有没有办法强制 MediaStore 也删除文件系统上的数据?为什么文件系统上的文件被遗忘了?