如何从default photo picker的URL可靠获取MediaStore资源及元数据?
通过默认照片选择器的URL获取MediaStore元数据
默认照片选择器返回的content://类型URL本身就对应MediaStore中的资源,你可以通过以下步骤获取对应的元数据:
1. 从URL中提取MediaStore资源ID
照片选择器返回的URL格式通常为content://media/external/images/media/xxx或content://media/external/video/media/xxx,末尾的数字就是该资源在MediaStore中的_ID字段值。你可以通过Uri对象解析出这个ID:
val pickerUri = // 从照片选择器获取的Uri实例 val mediaId = pickerUri.pathSegments.last() val isImage = pickerUri.toString().contains("images")
2. 查询MediaStore获取完整元数据
拿到资源ID后,通过ContentResolver查询对应的MediaStore表,即可获取文件名、大小、拍摄时间等元数据:
// 定义需要查询的元数据字段 val projection = arrayOf( MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.SIZE, MediaStore.Images.Media.DATE_TAKEN, MediaStore.Images.Media.MIME_TYPE ) // 构建查询条件 val selection = "${MediaStore.Images.Media._ID} = ?" val selectionArgs = arrayOf(mediaId) // 根据资源类型选择对应的MediaStore Uri val mediaUri = if (isImage) { MediaStore.Images.Media.EXTERNAL_CONTENT_URI } else { MediaStore.Video.Media.EXTERNAL_CONTENT_URI } // 执行查询并处理结果 contentResolver.query(mediaUri, projection, selection, selectionArgs, null)?.use { cursor -> if (cursor.moveToFirst()) { val fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)) val fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE)) val shootTime = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_TAKEN)) val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.MIME_TYPE)) // 这里处理获取到的元数据 } }
3. 权限注意事项
- Android 10(API 29)及以上:无需额外存储权限,照片选择器返回的Uri已附带临时访问权限,ContentResolver可直接查询。
- Android 9及以下:需提前申请
READ_EXTERNAL_STORAGE权限才能访问MediaStore数据。
特殊场景处理
如果遇到非标准的content:// Uri(比如来自第三方应用的自定义内容提供者),上述方法可能失效,此时可以通过通用字段查询基础元数据:
val basicProjection = arrayOf( OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE ) contentResolver.query(pickerUri, basicProjection, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { val fileName = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)) val fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(OpenableColumns.SIZE)) // 处理基础元数据 } }
这种方式只能获取文件名、大小等通用信息,无法获取拍摄时间这类MediaStore特有的元数据。
内容的提问来源于stack exchange,提问作者Nicolas Degen
相关产品推荐
相关产品推荐

