英文:
Android - all file access permission - how to get sd card data
问题
我正在为我的个人用例创建一个应用程序,其功能如下。
我想按照创建日期将照片分类到文件夹中。例如,文件夹的名称类似于2023-01、2023-02,并将照片按创建时间排序放入这些文件夹中。
我有照片存储在SD卡上。
问题是:我无法访问SD卡。我已经授予了ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION权限。但是以下任何方法都没有为我提供SD卡的路径:
context.getExternalFilesDirs(null)
返回一个包含两个对象的数组,但其中一个对象为空
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
指向内部存储
File("/sdcard")
一开始看起来好像可以,但所有数据都来自内部存储而不是SD卡
我需要获取类似这样的路径:/storage/7B32-B4556/
这对我来说真的很令人沮丧。我还尝试运行以下代码:
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
chooseDirectoryRequestLauncher.launch(intent)
但它给我一个不明确的“content” URI,我无法从中获取绝对文件路径。我不想使用存储API。
这是我目标的API:
compileSdk 34
defaultConfig {
applicationId "com.cndgf.photosorter"
minSdk 30
targetSdk 34
versionCode 1
versionName "1.0"
}
这是清单中的权限配置:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.PERMISSIONS_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_EXTERNAL_STORAGE" />
谢谢。
英文:
I'm creating an app for my own use case which is following.
I want to sort photos to the folders by date creation. eg. Folders with names like 2023-01, 2023-02 and put photos there sorted by creation time.
I have photos on sd-card
The problem: I can not access sd card. I have permission ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION granted. But nothing from the following gives me path to the sdcard:
context.getExternalFilesDirs(null)
gives me array with two object but one of them is null
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
points to internal storage
File("/sdcard")
at first it looks like it works, but all data are from internal storage not sd card
I need to get some path like this: /storage/7B32-B4556/
This is really frustrating for me. I have also tried runnning
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
chooseDirectoryRequestLauncher.launch(intent)
but it gives me some obsucre "content" uri and I'm not able to get absolute file path from it. I do not want to use storage api.
This is the api I'm targeting to
compileSdk 34
defaultConfig {
applicationId "com.cndgf.photosorter"
minSdk 30
targetSdk 34
versionCode 1
versionName "1.0"
this is how the permissions in manifest looks like:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.PERMISSIONS_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_EXTERNAL_STORAGE" />
Thank you
答案1
得分: 1
这是有关如何使用MediaStore API按创建日期组织照片的分步指南,而不直接访问SD卡的方法:
- 请求必要的权限:
确保您的应用清单包含READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限。
如果您的应用目标是Android 6.0(Marshmallow)或更高版本,您还需要在运行时请求这些权限。
- 使用MediaStore API检索照片的元数据:
MediaStore API允许您访问媒体文件,如照片,而不管它们的存储位置如何。
您可以查询MediaStore以获取必要的信息,例如照片的ID、文件路径和创建日期。
- 遍历检索到的数据:
一旦您从MediaStore查询中获得了游标,循环遍历数据以处理每张照片。
对于每张照片,提取其文件路径(DATA)和创建日期(DATE_TAKEN)。
- 根据创建日期将照片组织到文件夹中:
创建一个与您期望的格式相匹配的文件夹结构,例如"YYYY-MM"(例如"2023-01")。
从每张照片的创建日期中提取年份和月份。
使用这些值构建目标目录路径,将照片移动到其中。
- 将照片移动到相应的文件夹中:
一旦您具有源文件路径和目标目录路径,将照片从当前位置移动到适当的文件夹。
使用文件操作(例如重命名或复制)将照片移动到所需的文件夹。
在循环中为每张照片重复此过程。
请记住,在过程中处理可能发生的任何异常或错误,并向用户提供适当的反馈或错误处理。通过遵循这些步骤,您可以按创建日期组织照片,而无需直接访问SD卡。
英文:
Here's a step-by-step guide on how to organize your photos by creation date using the MediaStore API without directly accessing the SD card:
Request the necessary permissions:
Make sure your app's manifest includes the READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions.
If your app targets Android 6.0 (Marshmallow) or above, you'll need to request these permissions at runtime as well.
Use the MediaStore API to retrieve the photos' metadata:
The MediaStore API allows you to access media files, such as photos, regardless of their storage location.
You can query the MediaStore to fetch the necessary information, such as the photo's ID, file path, and creation date.
Iterate through the retrieved data:
Once you have the cursor from the MediaStore query, loop through the data to process each photo.
For each photo, extract its file path (DATA) and creation date (DATE_TAKEN).
Organize the photos into folders based on their creation date:
Create a folder structure that matches your desired format, such as "YYYY-MM" (e.g., "2023-01").
Extract the year and month from the creation date of each photo.
Use these values to construct the destination directory path where the photo will be moved.
Move the photos to the respective folders:
Once you have the source file path and the destination directory path, move the photo from its current location to the appropriate folder.
Use file manipulation operations (e.g., renaming or copying) to move the photo to the desired folder.
Repeat this process for each photo in the loop.
Remember to handle any exceptions or errors that may occur during the process and provide appropriate feedback or error handling to the user.
By following these steps, you can organize your photos by their creation date without directly accessing the SD card.
答案2
得分: 0
它给我一些模糊的“content” URI,我无法从中获取绝对文件路径。
对于目录的内容方案 URI 没有什么模糊的地方。您可以进一步使用 SAF 来列出该目录中的文件,并读取这些文件。
不需要文件系统路径。当 getExternalFilesDirs() 不提供它时,它甚至不存在。
您不需要任何权限来使用 SAF。
英文:
>> it gives me some obsucre "content" uri and I'm not able to get absolute file path from it.
There is nothing obscure on a content scheme uri for a directory. You can just further use SAF to list the files in that directory. And to read those files.
No need for a file system path. Which does not even exists when getExternalFilesDirs() does not deliver it.
You do not need any permission to use SAF.
答案3
得分: 0
这似乎是我正在寻找的内容:
val storageService = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
val volumes = storageService.storageVolumes
它还提供了SD卡的位置。
英文:
I guess this is what I was looking for
val storageService = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
val volumes = storageService.storageVolumes
it gives also sd card location
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论