为什么 CameraX.bindToLifecycle 在 1.0.0-alpha05 中不支持三例?

Why doesn't CameraX.bindToLifecycle support three cases in 1.0.0-alpha05?

正在学习CameraXAPI,CameraXBasic是office示例代码

代码A基于CameraFragment.kt

我添加 videoCaptureConfig,并使用 CameraX.bindToLifecycle(viewLifecycleOwner, preview, imageCapture,videoCapture).

将其绑定到生命周期

但是我得到以下错误,为什么?

java.lang.IllegalArgumentException:未找到相机设备支持的表面组合 - ID:0。可能试图绑定太多用例。

代码A

@SuppressLint("RestrictedApi")
private fun bindCameraUseCases() {

    // Get screen metrics used to setup camera for full screen resolution
    val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }
    val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)

    // Set up the view finder use case to display camera preview
    val viewFinderConfig = PreviewConfig.Builder().apply {
        setLensFacing(lensFacing)
        // We request aspect ratio but no resolution to let CameraX optimize our use cases
        setTargetAspectRatio(screenAspectRatio)
        // Set initial target rotation, we will have to call this again if rotation changes
        // during the lifecycle of this use case
        setTargetRotation(viewFinder.display.rotation)
    }.build()

    // Use the auto-fit preview builder to automatically handle size and orientation changes
    preview = AutoFitPreviewBuilder.build(viewFinderConfig, viewFinder)


    // Set up the capture use case to allow users to take photos
    val imageCaptureConfig = ImageCaptureConfig.Builder().apply {
        setLensFacing(lensFacing)
        setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
        // We request aspect ratio but no resolution to match preview config but letting
        // CameraX optimize for whatever specific resolution best fits requested capture mode
        setTargetAspectRatio(screenAspectRatio)
        // Set initial target rotation, we will have to call this again if rotation changes
        // during the lifecycle of this use case
        setTargetRotation(viewFinder.display.rotation)
    }.build()

    imageCapture = ImageCapture(imageCaptureConfig)


    // Create a configuration object for the video use case
    val videoCaptureConfig = VideoCaptureConfig.Builder().apply {
        setTargetRotation(viewFinder.display.rotation)
        setTargetAspectRatio(screenAspectRatio)
        setLensFacing(lensFacing)
    }.build()
    videoCapture = VideoCapture(videoCaptureConfig)


    CameraX.bindToLifecycle(viewLifecycleOwner, preview, imageCapture,videoCapture)
}

您尝试向同一个摄像头会话添加太多用例。你可以检查这个 github-issue about that. For understand limitations of camera sessions you can check documentation.

您可以尝试在切换到视频之前解绑所有用例(我注意到仅解绑 imageCapture 用例时旧手机会崩溃):

// Listener for button photo
btnPhoto.setOnClickListener( v -> bindCameraUseCases(0));
// Listener for button video
btnVideo.setOnClickListener( v -> bindCameraUseCases(1));

示例 camerax_version = "1.0.0-alpha06" (JAVA)

@SuppressLint("RestrictedApi")
private void bindCameraUseCases(int captureMode) {
    CameraX.unbindAll();

    AspectRatio screenAspectRatio = AspectRatio.RATIO_4_3;

    // Set up the preview use case to display camera preview
    PreviewConfig.Builder previewConfigBuilder = new PreviewConfig.Builder();
    previewConfigBuilder.setLensFacing(lensFacing);
    previewConfigBuilder.setTargetRotation(viewFinder.getDisplay().getRotation());
    previewConfigBuilder.setTargetAspectRatio(screenAspectRatio);
    Preview preview = new Preview(previewConfigBuilder.build());

    preview.setOnPreviewOutputUpdateListener(previewOutput -> {
        ViewGroup parent = (ViewGroup) viewFinder.getParent();
        parent.removeView(viewFinder);
        parent.addView(viewFinder,0);
        viewFinder.setSurfaceTexture(previewOutput.getSurfaceTexture());
    });

    if(captureMode == 0){ // IMAGE
        videoCapture = null;
        // Set up the capture use case to allow users to take photos
        ImageCaptureConfig.Builder imageCaptureConfigBuilder = new ImageCaptureConfig.Builder();
        imageCaptureConfigBuilder.setLensFacing(lensFacing);
        imageCaptureConfigBuilder.setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY);
        imageCaptureConfigBuilder.setTargetRotation(viewFinder.getDisplay().getRotation());
        imageCapture = new ImageCapture(imageCaptureConfigBuilder.build());

        // Apply declared configs to CameraX using the same lifecycle owner
        CameraX.bindToLifecycle(this, preview, imageCapture);
    }else{ // VIDEO
        imageCapture = null;
        // Set up the video capture use case to allow users to take videos
        VideoCaptureConfig.Builder videoCaptureConfigBuilder = new VideoCaptureConfig.Builder();
        videoCaptureConfigBuilder.setLensFacing(lensFacing);
        videoCaptureConfigBuilder.setTargetAspectRatio(screenAspectRatio);
        videoCaptureConfigBuilder.setTargetRotation(viewFinder.getDisplay().getRotation());
        videoCapture = new VideoCapture(videoCaptureConfigBuilder.build());

        // Apply declared configs to CameraX using the same lifecycle owner
        CameraX.bindToLifecycle(this, preview, videoCapture);
    }
}

示例 camerax_version = "1.0.0-alpha07" (JAVA)

@SuppressLint("RestrictedApi")
private void bindCameraUseCases(int captureMode) {
    if(cameraProvider != null) cameraProvider.unbindAll();

    // Set up the preview use case to display camera preview
    Preview preview = new Preview.Builder()
            .setTargetAspectRatio(AspectRatio.RATIO_4_3)
            .setTargetRotation(previewView.getDisplay().getRotation())
            .build();

    preview.setPreviewSurfaceProvider(previewView.getPreviewSurfaceProvider());

    if(captureMode == 0){ // IMAGE
        videoCapture = null;
        // Set up the capture use case to allow users to take photos
        imageCapture = new ImageCapture.Builder()
                .setCaptureMode(ImageCapture.CaptureMode.MINIMIZE_LATENCY)
                .setTargetRotation(previewView.getDisplay().getRotation())
                .build();

        // Apply declared configs using the same lifecycle owner
        cameraProvider.bindToLifecycle(this,cameraSelector, preview, imageCapture);
    }else{ // VIDEO
        imageCapture = null;
        // Set up the video capture use case to allow users to take videos
        VideoCaptureConfig.Builder videoCaptureConfigBuilder = new VideoCaptureConfig.Builder();
        videoCaptureConfigBuilder.setTargetAspectRatio(AspectRatio.RATIO_4_3);
        videoCaptureConfigBuilder.setTargetRotation(previewView.getDisplay().getRotation());
        videoCapture = new VideoCapture(videoCaptureConfigBuilder.getUseCaseConfig());

        // Apply declared configs using the same lifecycle owner
        cameraProvider.bindToLifecycle(this, cameraSelector,preview, videoCapture);
    }
}