Android中如何通过registerActivityResult获取录制视频的URI?
问题分析与修复方案
你代码中的编译报错主要来自以下几个核心问题,我会逐一说明并给出修正后的完整代码:
关键错误点
- 回调参数类型不匹配:
ActivityResultContracts.CaptureVideo()的回调接收的是Boolean类型(表示录制是否成功),而非Uri?,你写的{ uri: Uri? ->会直接导致类型不匹配编译错误。 - 未定义变量引用:
recordVideoResult.launch(this.uri)中的this.uri是不存在的变量,你声明的成员变量是videoUri,且即使改成videoUri,未初始化的null值也不符合CaptureVideo的参数要求(必须传入有效存储Uri)。 - 缺少视频存储Uri创建逻辑:录制视频需要提前生成一个系统可写入的Uri,用于存储录制后的视频文件。
修正后的完整代码
1. 成员变量声明
private var videoUri: Uri? = null
2. 注册Activity Result Launcher
// 视频录制结果回调:参数是Boolean,表示录制是否成功 private val recordVideoResult = registerForActivityResult(ActivityResultContracts.CaptureVideo()) { isRecordingSuccess -> if (isRecordingSuccess) { // 录制成功,videoUri就是视频的存储路径 Toast.makeText(this, "视频录制完成", Toast.LENGTH_SHORT).show() } else { // 录制取消或失败,清空无效的Uri videoUri = null Toast.makeText(this, "视频录制取消或失败", Toast.LENGTH_SHORT).show() } } // 相机权限申请回调 private val requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted -> if (isGranted) { launchCamera() } else { Toast.makeText(this, "无法打开相机:权限被拒绝,请在设置中开启权限", Toast.LENGTH_SHORT).show() } }
3. 添加视频存储Uri创建方法
该方法适配Android 10+的分区存储规则,无需额外申请存储权限(Android 9及以下需在Manifest中声明WRITE_EXTERNAL_STORAGE权限):
private fun createVideoUri(): Uri? { val videoFileName = "录制视频_${System.currentTimeMillis()}.mp4" val contentValues = ContentValues().apply { put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName) put(MediaStore.Video.Media.MIME_TYPE, "video/mp4") // Android 10+ 指定存储到系统Movies目录 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES) } } return contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues) }
4. 修正相机启动方法
fun launchCamera() { if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) { when { ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -> { // 先创建视频存储Uri,再启动相机 videoUri = createVideoUri() videoUri?.let { uri -> recordVideoResult.launch(uri) } ?: run { Toast.makeText(this, "创建视频文件失败", Toast.LENGTH_SHORT).show() } } else -> { requestPermissionLauncher.launch(Manifest.permission.CAMERA) } } } else { Toast.makeText(this, "设备无可用相机", Toast.LENGTH_SHORT).show() } }
额外注意事项
在AndroidManifest.xml中声明必要权限:
<uses-permission android:name="android.permission.CAMERA" /> <!-- 兼容Android 9及以下的存储权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
registerForActivityResult必须在Activity/Fragment的创建阶段(如onCreate方法、成员变量初始化)注册,不能在点击事件等动态场景中注册。
内容的提问来源于stack exchange,提问作者Darrell Gehring
相关产品推荐
相关产品推荐

