You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 09:05:37