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

Android 9导出视频到图库不显示且ContentValues设置的名称异常

问题修复方案

1. 导出视频无法在图库即时显示问题

原因:你调用MediaScannerConnection.scanFile时传入的是content://格式的MediaStore URI,该方法要求传入本地文件绝对路径作为扫描参数,错误参数导致扫描逻辑未生效,只有其他全局扫描事件触发时才会识别到新视频。
额外适配点:Android 9系统上插入MediaStore时建议显式声明文件存储路径,避免系统生成随机路径无法获取实际文件地址。

2. 视频标题/显示名称与设置不符问题

原因:扫描逻辑未正常生效时,后续第三方触发的全局扫描会重新读取视频元数据生成MediaStore记录,覆盖你提前插入时设置的TITLE和DISPLAY_NAME字段;此外如果未设置DATE_MODIFIED等必要字段,三星等定制系统的图库会优先读取文件属性作为展示值。

修复后完整代码
fun exportInGallery(videoFileName: String, videoPathToCopy: String,context: Context, onCompletion: (String) -> Unit){
    // Android 9 显式指定存储路径到DCIM目录下的自定义文件夹(可自行修改文件夹名)
    val dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
    val targetDir = File(dcimDir, "MyAppVideos")
    if (!targetDir.exists()) targetDir.mkdirs()
    val targetFilePath = File(targetDir, videoFileName).absolutePath

    val valuesVideo = ContentValues()
    valuesVideo.put(MediaStore.Video.Media.TITLE, videoFileName.substringBeforeLast(".")) // 不带后缀的作为标题
    valuesVideo.put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName) // 带后缀的作为显示名
    valuesVideo.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
    val currentTime = System.currentTimeMillis() / 1000
    valuesVideo.put(MediaStore.Video.Media.DATE_ADDED, currentTime)
    valuesVideo.put(MediaStore.Video.Media.DATE_MODIFIED, currentTime)
    // Android 9 可用DATA字段指定存储路径
    valuesVideo.put(MediaStore.Video.Media.DATA, targetFilePath)

    // 可选:如果能拿到视频时长可以补充,提升识别率
    // val retriever = MediaMetadataRetriever()
    // retriever.setDataSource(videoPathToCopy)
    // val duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0
    // valuesVideo.put(MediaStore.Video.Media.DURATION, duration)
    // retriever.release()

    val savedUri = context.contentResolver.insert(
        MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
        valuesVideo
    )!!

    try {
        context.contentResolver.openFileDescriptor(savedUri, "w")?.use { pfd ->
            FileOutputStream(pfd.fileDescriptor).use { out ->
                File(videoPathToCopy).inputStream().use { input ->
                    input.copyTo(out, 8192)
                }
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }

    // 传入实际文件路径扫描,而不是content uri
    MediaScannerConnection.scanFile(context, arrayOf(targetFilePath), arrayOf("video/mp4")
    ) { path, uri ->
        Log.i("ExternalStorage", "Scanned $path:")
        Log.i("ExternalStorage", "-> uri=$uri")
        onCompletion(savedUri.toString())
    }
}
注意事项
  • 需要提前申请android.permission.WRITE_EXTERNAL_STORAGE权限,Android 9上该权限为运行时权限,必须用户授权后才能正常写入公共存储
  • 如果你的videoFileName包含特殊字符,建议提前做一次非法字符过滤,避免部分厂商文件系统不兼容导致写入失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 00:48:04