Nic*_*hek 6 android uri file file-manager android-contentresolver
Documents/MyExcelsFolder 我通过使用添加了文件ContentResolver.insert,然后还Documents/MyExcelsFolder通过另一个应用程序将新文件添加到了文件夹(例如FileManager)
MyExcelsFolder然后我尝试从文件夹中获取所有文件
fun getAppFiles(context: Context): List<AppFile> {
val appFiles = mutableListOf<AppFile>()
val contentResolver = context.contentResolver
val columns = mutableListOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.MIME_TYPE
).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
add(
MediaStore.MediaColumns.RELATIVE_PATH
)
}
}.toTypedArray()
val extensions = listOf("xls", "xlsx")
val mimes = extensions.map { MimeTypeMap.getSingleton().getMimeTypeFromExtension(it) }
val selection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
"${MediaStore.MediaColumns.RELATIVE_PATH} LIKE ?"
} else {
"${MediaStore.Images.Media.DATA} LIKE ?"
}
val selectionArgs = arrayOf(
"%${Environment.DIRECTORY_DOCUMENTS}/MyExcelsFolder%"
)
contentResolver.query(
MediaStore.Files.getContentUri("external"),
columns,
selection,
selectionArgs,
MediaStore.Files.FileColumns.DATE_ADDED + " DESC"
)?.use { cursor ->
while (cursor.moveToNext()) {
val pathColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
val mimeColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)
val filePath = cursor.getString(pathColumnIndex)
val mimeType = cursor.getString(mimeColumnIndex)
if (mimeType != null && mimes.contains(mimeType)) {
// handle cursor
appFiles.add(cursor.toAppFile())
} else {
// need to check extension, because the Mime Type is null
val extension = File(filePath).extension
if (extensions.contains(extension)) {
// handle cursor
appFiles.add(cursor.toAppFile())
}
}
}
}
return appFiles
}
fun Cursor.toAppFile(): AppFile {
val cursor = this
val idColumnIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID)
val nameColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
val mimeColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)
val pathColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
val id = cursor.getLong(idColumnIndex)
val uri = ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"), id)
val fileDisplayName = cursor.getString(nameColumnIndex)
val filePath = cursor.getString(pathColumnIndex)
var mimeType = cursor.getString(mimeColumnIndex)
val relativePath = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.RELATIVE_PATH))
} else {
null
}
var type = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType)
if (type == null) {
type = File(filePath).extension
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(type)
}
return AppFile(
id = id,
uri = uri,
absolutePath = filePath,
name = fileDisplayName,
mimeType = mimeType,
extension = type,
relativePath = relativePath
)
}
Run Code Online (Sandbox Code Playgroud)
结果只有命令ContentResolver添加的文件insert,没有FileManager复制的文件。如何查看 中的所有文件cursor?
操作系统:Android 10 (Q)(API 级别 29)
目标 API 版本:api 29
从 Android 10 开始,出现了一种新的存储访问模型,称为“作用域存储”,它的限制性更强。简而言之:
ContentResolver.insert)到共享媒体集合,并且只能从中读取您的应用程序创建的文件。您可以通过请求权限来访问这些集合中的其他应用程序文件READ_EXTERNAL_STORAGE。这有点奇怪,看起来像是一个错误,您可以xls通过集合访问文件MediaStore.Files。文档说
媒体商店还包括一个名为 的集合
MediaStore.Files。其内容取决于您的应用是否使用范围存储,适用于面向 Android 10 或更高版本的应用:如果启用了范围存储,则该集合仅显示您的应用创建的照片、视频和音频文件。
如果范围存储不可用或未使用,则该集合会显示所有类型的媒体文件。
但无论如何,您仍然无法访问上述其他应用程序创建的文件。因此,根据您的用例,有以下几种选择:
MediaStore.Files,您可以尝试请求此表READ_EXTERNAL_STORAGE中所示的权限,以获得对媒体集合的非过滤访问。但我希望这种方式在不同的设备上工作不可靠,并且/或者希望停止它与新的更新一起工作,因为媒体集合应该仅用于媒体文件。ACTION_OPEN_DOCUMENT或ACTION_OPEN_DOCUMENT_TREE向用户显示文件/目录选择器并访问文件或整个目录树。另请检查此方法的限制。我想说这是最好的方法。android:requestLegacyExternalStorage范围存储。但 Android 11 已经发布,该标志对其没有任何影响。MANAGE_EXTERNAL_STORAGE权限,然后请求用户将其列入特殊的白名单以访问所有文件。这就是文件管理器现在的工作方式。此功能从 Android 11 开始可用,因此您可能会使用 Android 10 的选择退出标志。如果您打算在 Google Play 发布应用程序,请务必检查有关使用此功能的限制和 Google Play 政策。| 归档时间: |
|
| 查看次数: |
1092 次 |
| 最近记录: |