CameraX:用 use case 组装相机 · AndroidX 源码指南
AAndroidX 源码指南
设备能力
设备能力 · androidx.camera

CameraX:用 use case 组装相机Camera 1.7.0-alpha03

PreviewView、Preview、ImageCapture、ImageAnalysis 与 VideoCapture 的完整管线。

最后更新 2026-08-01

复制即用:预览 + 拍照

class CameraFragment : Fragment() {

    private var imageCapture: ImageCapture? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val previewView = view.findViewById<PreviewView>(R.id.preview_view)

        val providerFuture = ProcessCameraProvider.getInstance(requireContext())

        providerFuture.addListener({
            val provider = providerFuture.get()
            val preview = Preview.Builder().build().also {
                it.surfaceProvider = previewView.surfaceProvider
            }
            imageCapture = ImageCapture.Builder().build()

            provider.unbindAll()
            provider.bindToLifecycle(
                viewLifecycleOwner,
                CameraSelector.DEFAULT_BACK_CAMERA,
                preview,
                imageCapture,
            )
        }, ContextCompat.getMainExecutor(requireContext()))
    }

    fun takePhoto(onSaved: (Uri) -> Unit) {
        val capture = imageCapture ?: return
        val name = "photo_${System.currentTimeMillis()}.jpg"
        val options = ImageCapture.OutputFileOptions.Builder(
            File(externalMediaDirs.first(), name)
        ).build()

        capture.takePicture(
            options,
            ContextCompat.getMainExecutor(requireContext()),
            object : ImageCapture.OnImageSavedCallback {
                override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                    outputFileResults.savedUri?.let(onSaved)
                }

                override fun onError(exc: ImageCaptureException) {
                    // 处理错误
                }
            },
        )
    }
}

四个 use case

Use Case职责
Preview预览输出(绑定 surfaceProvider
ImageCapture单张照片
ImageAnalysis逐帧分析(二维码、人脸)
VideoCapture录像

不要把所有工作塞进预览回调——每类 use case 职责独立。

ImageAnalysis:记得关闭帧

val analysis = ImageAnalysis.Builder()
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .build()

analysis.setAnalyzer(Executors.newSingleThreadExecutor()) { imageProxy ->
    // 处理 imageProxy
    try {
        val buffer = imageProxy.planes[0].buffer
        // ... 分析
    } finally {
        imageProxy.close()   // 必须关闭,否则阻塞后续帧
    }
}
  • 每个 ImageProxy 处理完必须 close()
  • STRATEGY_KEEP_ONLY_LATEST:分析跟不上时丢弃旧帧保最新。
  • 分析器放独立线程(别阻塞相机回调)。

CameraSelector:前后摄

// 后摄(默认)
CameraSelector.DEFAULT_BACK_CAMERA

// 前摄
CameraSelector.DEFAULT_FRONT_CAMERA

// 根据需求选(如有前置摄像头)
val selector = CameraSelector.Builder()
    .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
    .build()

生命周期绑定

bindToLifecycle 把 use case 绑定到 LifecycleOwner

  • Fragment 用 viewLifecycleOwner(View 销毁解绑)。
  • Activity 用 this
  • 离开页面自动释放相机;unbindAll() 手动释放。

常见陷阱

  • 权限没申请:CameraX 不绕过平台权限,先 CAMERA 权限。
  • 忘 close ImageProxy:后续帧全阻塞。
  • bindToLifecycle 用错 owner:用 Fragment lifecycle 而非 viewLifecycleOwner,View 销毁后相机还在。
  • 拍照 URI 用错目录externalMediaDirs 是 MediaStore 不可见的文件目录;要进相册用 MediaStore 或 PickVisualMedia
  • provider 单例ProcessCameraProvider.getInstance 是单例,重复拿无副作用。

依赖

implementation("androidx.camera:camera-core:1.7.0-alpha03")
implementation("androidx.camera:camera-camera2:1.7.0-alpha03")
implementation("androidx.camera:camera-lifecycle:1.7.0-alpha03")
implementation("androidx.camera:camera-view:1.7.0-alpha03")

要点

  • 四个 use case 各司其职;provider 绑定生命周期。
  • ImageProxy 必须 close;KEEP_ONLY_LATEST 保最新帧。
  • 权限与硬件独占需自行处理;CameraX 不做这些。
  • Fragment 用 viewLifecycleOwner 绑定。

相关页面