
本文详解 CameraX VideoCapture 录制视频后,如何在 VideoRecordEvent.Finalize 事件中安全、规范地提取已保存视频的 Uri,避免反射或私有字段访问,并提供可直接复用的代码示例与关键注意事项。
本文详解 camerax `videocapture` 录制视频后,如何在 `videorecordevent.finalize` 事件中安全、规范地提取已保存视频的 `uri`,避免反射或私有字段访问,并提供可直接复用的代码示例与关键注意事项。
在使用 CameraX 的 VideoCapture 进行视频录制时,开发者常需在录制结束后续处理视频文件(如上传、预览、裁剪等),而获取保存路径的核心前提就是拿到系统写入完成后的 Uri。CameraX 并未在 Recording 对象上暴露 getOutputUri() 方法,正确的路径是:从 VideoRecordEvent.Finalize 事件实例中提取——这是官方唯一支持且稳定的公开 API。
✅ 正确获取方式(推荐)
VideoRecordEvent.Finalize 是录制完成(含成功/失败)的最终回调事件,其 getOutputResults() 方法返回 VideoRecordEvent.Finalize.OutputResults 对象,该对象提供 getOutputUri() 方法,返回 Uri(若录制成功)或 null(若失败)。示例代码如下:
recording = videoCapture.getOutput()
.prepareRecording(this, mediaStoreOutputOptions) // 或 FileOutputOptions
.start(ContextCompat.getMainExecutor(this), new Consumer<VideoRecordEvent>() {
@Override
public void accept(VideoRecordEvent event) {
if (event instanceof VideoRecordEvent.Start) {
// 录制开始:更新 UI,例如显示红点、禁用按钮
setBackgroundBtn(R.drawable.recoding);
Toast.makeText(CameraActivity.this, "Recording started...", Toast.LENGTH_SHORT).show();
} else if (event instanceof VideoRecordEvent.Finalize) {
VideoRecordEvent.Finalize finalizeEvent = (VideoRecordEvent.Finalize) event;
// ✅ 官方推荐:通过 OutputResults 获取 Uri
Uri savedUri = finalizeEvent.getOutputResults().getOutputUri();
if (savedUri != null) {
// 成功保存,可进行后续操作(如播放、分享、查询媒体库)
Toast.makeText(CameraActivity.this,
"Video saved to: " + savedUri.toString(),
Toast.LENGTH_LONG).show();
// 示例:触发媒体扫描(仅对非 MediaStore 输出必要)
// sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, savedUri));
} else {
// 录制失败(如磁盘满、权限拒绝、编码异常)
Toast.makeText(CameraActivity.this,
"Recording failed: " + finalizeEvent.getReason(),
Toast.LENGTH_LONG).show();
}
}
}
});⚠️ 注意事项与最佳实践
- 不可依赖反射或内部字段:如 recording.mRecorder.mOutputUri.uriString 属于私有实现细节,不仅违反封装原则,更会在 CameraX 版本升级后失效(已有多起兼容性问题报告)。
-
getOutputUri() 返回值含义明确:
- 使用 MediaStoreOutputOptions 时,返回的是 content:// URI(如 content://media/external/videos/media/12345),可直接用于 ContentResolver 操作;
- 使用 FileOutputOptions 时,返回的是 file:// URI(Android 7.0+ 需配合 FileProvider 使用)。
- 必须检查 null 值:getOutputUri() 在录制失败、取消或未写入时返回 null,务必判空,避免 NullPointerException。
- 线程安全:VideoRecordEvent 回调默认在 Executor 指定的线程执行(如主线程),UI 操作(如 Toast)可直接进行;但文件 I/O 或耗时操作建议切至后台线程。
-
权限与存储适配:
- Android 10+(API 29+)推荐优先使用 MediaStoreOutputOptions,避免分区存储(Scoped Storage)限制;
- 若使用 FileOutputOptions,需动态申请 WRITE_EXTERNAL_STORAGE(旧设备)或确保目录位于应用专属目录(如 getExternalFilesDir())。
✅ 总结
获取 CameraX 视频录制 URI 的唯一标准做法,是在 VideoRecordEvent.Finalize 事件中调用 event.getOutputResults().getOutputUri()。该方式简洁、稳定、符合官方设计契约,无需绕行反射或解析日志。结合合理的错误处理与存储策略,即可构建健壮的视频录制功能。









