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

Android Studio中能否通过Cursor提取单个音视频文件元数据?

用Cursor提取单个音视频文件元数据的方法

当然可以通过Cursor搭配MediaStore提取单个音视频文件的元数据,这种方式比遍历全部媒体文件效率更高,核心是通过目标文件的Content URI精准查询对应的媒体表。下面是具体实现步骤:

一、权限准备

  • Android 13及以上:需要申请READ_MEDIA_AUDIO(音频)或READ_MEDIA_VIDEO(视频)权限
  • Android 12及以下:需要申请READ_EXTERNAL_STORAGE权限
    注意:所有权限都需要动态申请,确保用户授权后再执行查询操作。

二、获取目标文件的Content URI

如果是通过系统文件选择器获取的文件,能直接拿到对应的Content URI;如果仅知道文件路径,Android 10及以上推荐通过MediaStore查询匹配的URI,避免Scoped Storage限制,示例代码如下:

fun getUriFromFilePath(context: Context, filePath: String): Uri? {
    val projection = arrayOf(MediaStore.Audio.Media._ID)
    val selection = "${MediaStore.Audio.Media.DATA} = ?"
    val selectionArgs = arrayOf(filePath)
    
    context.contentResolver.query(
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
        projection,
        selection,
        selectionArgs,
        null
    )?.use { cursor ->
        if (cursor.moveToFirst()) {
            val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID))
            return ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id)
        }
    }
    return null
}

(视频文件只需把MediaStore.Audio替换为MediaStore.Video即可)

三、查询并解析元数据

拿到目标文件的Content URI后,就可以通过ContentResolver.query()获取Cursor,进而提取元数据。

音频文件示例

fun getSingleAudioMeta(context: Context, audioUri: Uri) {
    // 定义需要提取的元数据字段
    val projection = arrayOf(
        MediaStore.Audio.Media.TITLE,
        MediaStore.Audio.Media.ARTIST,
        MediaStore.Audio.Media.ALBUM,
        MediaStore.Audio.Media.DURATION,
        MediaStore.Audio.Media.SIZE
    )

    context.contentResolver.query(
        audioUri,
        projection,
        null,
        null,
        null
    )?.use { cursor ->
        // Cursor中只会有一条数据(对应单个文件)
        if (cursor.moveToFirst()) {
            val title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE))
            val artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)) ?: "未知艺术家"
            val album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM)) ?: "未知专辑"
            val duration = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION))
            val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE))
            
            // 这里可以根据需求处理元数据
            println("标题:$title")
            println("艺术家:$artist")
            println("专辑:$album")
            println("时长:${duration / 1000}秒")
            println("文件大小:${size / 1024 / 1024}MB")
        }
    }
}

视频文件示例

fun getSingleVideoMeta(context: Context, videoUri: Uri) {
    val projection = arrayOf(
        MediaStore.Video.Media.TITLE,
        MediaStore.Video.Media.DURATION,
        MediaStore.Video.Media.WIDTH,
        MediaStore.Video.Media.HEIGHT,
        MediaStore.Video.Media.SIZE,
        MediaStore.Video.Media.DATE_ADDED
    )

    context.contentResolver.query(
        videoUri,
        projection,
        null,
        null,
        null
    )?.use { cursor ->
        if (cursor.moveToFirst()) {
            val title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE))
            val duration = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION))
            val width = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.WIDTH))
            val height = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.HEIGHT))
            val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE))
            val addedDate = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_ADDED))
            
            println("标题:$title")
            println("时长:${duration / 1000}秒")
            println("分辨率:${width}x${height}")
            println("文件大小:${size / 1024 / 1024}MB")
            println("添加时间:${Date(addedDate * 1000)}")
        }
    }
}

四、注意事项

  • 务必使用use函数包裹Cursor,确保Cursor自动关闭,避免内存泄漏
  • 部分元数据字段可能为空,需要添加非空判断,避免空指针异常
  • Android 10及以上不建议直接使用文件路径访问,优先通过Content URI操作媒体文件

内容的提问来源于stack exchange,提问作者Hanif Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:15:43