使用CameraX录制视频后,无法通过getSavedUri获取视频绝对路径
CameraX获取录制视频绝对路径问题解决
你的代码核心问题
- 回调调用错误:你在
start()方法后直接调用onVideoSaved(outputFileResults = androidx.camera.core.VideoCapture.OutputFileResults)完全错误,OutputFileResults是录制完成后系统返回的实例,不能直接传类。正确做法是把onVideoSaved作为start()的回调参数传入。 - Uri转路径误区:Android 10(API 29)及以上启用分区存储,
savedUri无法直接通过常规方法转为绝对路径,需要通过ContentResolver查询获取。
修正后的完整代码
private fun captureVideo() { val videoCapture = this.videoCapture ?: return val curRecording = recording if (curRecording != null) { // 停止当前录制 curRecording.stop() recording = null return } // 生成视频文件名 val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US) .format(System.currentTimeMillis()) val contentValues = ContentValues().apply { put(MediaStore.MediaColumns.DISPLAY_NAME, name) put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4") if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/CameraX-Video") } } val mediaStoreOutputOptions = MediaStoreOutputOptions .Builder(contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI) .setContentValues(contentValues) .build() recording = videoCapture.output .prepareRecording(this, mediaStoreOutputOptions) .apply { if (PermissionChecker.checkSelfPermission(this@MainActivity, Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) { withAudioEnabled() } } // 正确传入录制完成回调 .start(ContextCompat.getMainExecutor(this)) { outputFileResults -> onVideoSaved(outputFileResults) } } @SuppressLint("RestrictedApi") private fun onVideoSaved(outputFileResults: androidx.camera.core.VideoCapture.OutputFileResults) { val savedUri = outputFileResults.savedUri ?: return // 获取视频绝对路径 val videoPath = getRealPathFromUri(savedUri) // 这里可对videoPath做后续操作 } // 通过ContentResolver查询Uri对应的真实路径 private fun getRealPathFromUri(uri: Uri): String? { val projection = arrayOf(MediaStore.Video.Media.DATA) contentResolver.query(uri, projection, null, null, null)?.use { cursor -> return if (cursor.moveToFirst()) { val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA) cursor.getString(columnIndex) } else { null } } return null }
关键说明
- 回调修正:将
onVideoSaved放在start()的lambda参数中,录制完成后系统会自动传入OutputFileResults实例。 - 路径获取:
- Android 10以下:
MediaStore.Video.Media.DATA字段直接返回绝对路径。 - Android 10及以上:虽然分区存储限制了直接访问,但通过ContentResolver查询仍能获取真实路径(建议优先使用Uri操作文件,而非依赖绝对路径)。
- Android 10以下:
- 权限检查:确保已申请
WRITE_EXTERNAL_STORAGE(兼容低版本)和RECORD_AUDIO权限。
内容的提问来源于stack exchange,提问作者Hassaan Zahid
相关产品推荐
相关产品推荐

