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
相关产品推荐
相关产品推荐

