我正在使用 Kotlin 开发 Android 应用程序,我需要从设备存储中检索照片和视频列表。我读到 MediaStore 可用于此目的,但我不确定如何设置查询以有效地检索图像和视频。
这是我迄今为止尝试过的:
分别查询MediaStore.Images.Media和MediaStore.Video.Media,获取图片和视频。
使用 ContentResolver 访问媒体文件。
// 获取照片 val imageProjection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.DATE_ADDED) val imageCursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageProjection, null, null, null)
// 获取视频 val videoProjection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.DISPLAY_NAME, MediaStore.Video.Media.DATE_ADDED) val videoCursor = contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, videoProjection, null, null, null)
但是,我不确定这是否是最有效的方法,或者我是否应该使用特定列来优化查询。
我想要获取照片和视频的组合列表,其中包含文件名、URI 和添加日期等详细信息。该解决方案应该处理访问外部存储的运行时权限。
要使用 Kotlin 中的 MediaStore 高效地从设备存储中检索照片和视频的组合列表,您可以设置针对图像和视频内容类型的查询。通过使用 MediaStore.Files 表,您可以在单个查询中同时查询照片和视频,这比单独查询它们更高效。
我将为您提供完整的解决方案,其中包括:
1 - 请求必要的运行时权限。
2 - 查询 MediaStore 中的图像和视频。
3 - 检索文件名、URI 和添加日期等详细信息。
向AndroidManifest.xml添加权限 对于 Android 10 及以下版本:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
对于 Android 11(API 级别 30)及更高版本,如果您使用 MediaStore 访问媒体文件(照片和视频),则不需要额外的权限。
在 Kotlin 中处理权限 对于 Android 10 及更低版本,请使用 READ_EXTERNAL_STORAGE 权限:
private val storagePermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
fetchMediaFiles()
} else {
Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show()
}
}
private fun checkStoragePermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { // Android 9 and below
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
fetchMediaFiles()
} else {
storagePermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
}
} else {
// No runtime permission needed for MediaStore access on Android 10+
fetchMediaFiles()
}
}
查询 MediaStore 中的照片和视频
fun fetchMediaFiles(context: Context): List<MediaFile> {
val mediaList = mutableListOf<MediaFile>()
val projection = arrayOf(
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.DATE_ADDED
)
// Selection for images and videos only
val selection = "${MediaStore.Files.FileColumns.MEDIA_TYPE}=? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE}=?"
val selectionArgs = arrayOf(
MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(),
MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString()
)
val sortOrder = "${MediaStore.Files.FileColumns.DATE_ADDED} DESC"
val queryUri = MediaStore.Files.getContentUri("external")
val cursor = context.contentResolver.query(
queryUri,
projection,
selection,
selectionArgs,
sortOrder
)
cursor?.use {
val idColumn = it.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)
val nameColumn = it.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME)
val mimeTypeColumn = it.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MIME_TYPE)
val dateAddedColumn = it.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATE_ADDED)
while (it.moveToNext()) {
val id = it.getLong(idColumn)
val name = it.getString(nameColumn)
val mimeType = it.getString(mimeTypeColumn)
val dateAdded = it.getLong(dateAddedColumn)
val contentUri: Uri = ContentUris.withAppendedId(queryUri, id)
mediaList.add(MediaFile(id, name, contentUri, dateAdded, mimeType))
}
}
return mediaList
}