如何在Android应用的VideoView组件中打开并显示摄像头实时画面
问题根因
你当前使用的MediaStore.ACTION_IMAGE_CAPTURE意图是唤起系统相机应用完成拍照操作,逻辑本身就是跳转外部应用,无法实现将相机预览内嵌到你自有应用的组件中。
实现方案
优先推荐使用Jetpack CameraX实现,适配成本低、兼容性好,无需自行处理各机型适配问题;如果必须使用VideoView承载预览,可以用Camera2 API实现。
前置准备:配置权限
在AndroidManifest.xml中添加相机相关声明:
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera.any" />
Android 6.0及以上版本需要在运行时动态申请CAMERA权限,权限申请通过后再执行相机初始化逻辑。
方案1:Jetpack CameraX实现(推荐)
1. 引入依赖
在模块级build.gradle中添加CameraX依赖:
dependencies { def camerax_version = "1.3.0" implementation "androidx.camera:camera-core:$camerax_version" implementation "androidx.camera:camera-camera2:$camerax_version" implementation "androidx.camera:camera-lifecycle:$camerax_version" implementation "androidx.camera:camera-view:$camerax_version" }
2. 修改布局
把原有VideoView替换为CameraX专属预览组件:
<androidx.camera.view.PreviewView android:id="@+id/previewView" android:layout_width="366dp" android:layout_height="437dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.355" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.088" />
3. 初始化相机
权限申请通过后调用以下方法即可完成预览渲染:
private fun startCamera() { val cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ val cameraProvider = cameraProviderFuture.get() val preview = Preview.Builder().build().also { it.setSurfaceProvider(previewView.surfaceProvider) } // 配置为前置摄像头,和你原有需求对齐 val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA try { cameraProvider.unbindAll() // 绑定页面生命周期,页面销毁时自动释放相机 cameraProvider.bindToLifecycle(this, cameraSelector, preview) } catch(exc: Exception) { // 自行处理相机初始化失败逻辑 } }, ContextCompat.getMainExecutor(this)) }
方案2:Camera2 API输出到VideoView
如果必须保留原有VideoView组件,可通过以下核心逻辑实现预览输出:
1. 先给VideoView配置Surface
在页面初始化时添加配置:
videoView.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) videoView.holder.addCallback(object : SurfaceHolder.Callback { override fun surfaceCreated(holder: SurfaceHolder) { // Surface创建成功后再启动相机 startCameraToVideoView(holder.surface) } override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {} override fun surfaceDestroyed(holder: SurfaceHolder) {} })
2. 实现相机预览输出逻辑
@SuppressLint("MissingPermission") private fun startCameraToVideoView(surface: Surface) { val cameraManager = getSystemService(CAMERA_SERVICE) as CameraManager // 筛选前置摄像头 val frontCameraId = cameraManager.cameraIdList.firstOrNull { id -> cameraManager.getCameraCharacteristics(id) .get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT } ?: return val captureRequestBuilder = cameraManager.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) captureRequestBuilder.addTarget(surface) cameraManager.openCamera(frontCameraId, object : CameraDevice.StateCallback() { override fun onOpened(camera: CameraDevice) { camera.createCaptureSession( listOf(surface), object : CameraCaptureSession.StateCallback() { override fun onConfigured(session: CameraCaptureSession) { session.setRepeatingRequest(captureRequestBuilder.build(), null, null) } override fun onConfigureFailed(session: CameraCaptureSession) {} }, null ) } override fun onDisconnected(camera: CameraDevice) { camera.close() } override fun onError(camera: CameraDevice, error: Int) { camera.close() } }, null) }
内容的提问来源于stack exchange,提问作者Muhammad Uzair Ehsan
相关产品推荐
相关产品推荐

