MediaMetadataRetriever的setDataSource始终调用失败求助
解决方案
问题根源
- 原视频Uri构建错误:
android.resource类型的Uri格式要求为android.resource://[应用包名]/[资源类型]/[资源名称],你直接用R.raw.diamond的数值转字符串作为path,不符合规范,导致MediaMetadataRetriever无法识别资源路径。 - 编辑后视频的Uri scheme错误:缓存目录下的文件属于本地文件,应该使用
file://scheme,而非android.resource://,后者仅用于访问应用内置的raw、drawable等资源。
具体修复步骤
1. 修正原视频的Uri构建
替换原Uri构建代码为正确格式:
// 方式1:直接拼接Uri字符串 val videoUri = Uri.parse("android.resource://${context.packageName}/raw/diamond") // 方式2:使用Uri.Builder规范构建 val videoUri = Uri.Builder() .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) .authority(context.packageName) .appendPath("raw") .appendPath("diamond") .build()
2. 修正编辑后视频的Uri
假设你保存编辑后视频的File对象为editedVideoFile,构建正确的本地文件Uri:
val editedVideoUri = Uri.fromFile(editedVideoFile)
如果是直接通过缓存路径字符串构建:
val cachePath = context.cacheDir.path + "/editedVideo.mp4" val editedVideoUri = Uri.parse("file://$cachePath")
3. 额外检查点
- 缓存目录属于应用私有目录,不需要申请
READ_EXTERNAL_STORAGE或READ_MEDIA_VIDEO权限,可移除这些不必要的权限申请(仅处理应用私有文件时)。 - 确保编辑后的视频文件完整生成,可通过以下代码验证:
val editedFile = File(context.cacheDir, "editedVideo.mp4") if (editedFile.exists() && editedFile.length() > 0) { // 文件有效,继续处理 } else { // 文件生成失败,检查视频编辑逻辑 }
4. 优化MediaMetadataRetriever调用
增加空值判断,简化时间转换逻辑:
private fun getVideoFrame(context: Context?, uri: Uri?): Bitmap? { uri ?: return null context ?: return null var bitmap: Bitmap? = null val retriever = MediaMetadataRetriever() try { retriever.setDataSource(context, uri) val currentPosMicroSec = exoPlayer.currentPosition * 1000 // 直接转换为微秒 bitmap = retriever.getFrameAtTime(currentPosMicroSec) } catch (ex: RuntimeException) { ex.printStackTrace() } finally { try { retriever.release() } catch (ex: RuntimeException) { ex.printStackTrace() } } return bitmap }
内容的提问来源于stack exchange,提问作者Ivan Šimović
相关产品推荐
相关产品推荐

