Search code examples
androidandroid-camerax

Rebinding CameraX UseCases


I am trying to stop/pause the camera PreviewView during image processing/detection using Firebase MLKit. To pause the preview I call

cameraProvider.unbind(previewUseCase)

That stops the preview on the last frame but now I dont know how to restart it. I tried just binding the preview again like this

cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview)

But that causes the PreviewView to just show white like its gone and cant get it back ntil restart the app.

The same thing happens when I call unbindAll()

So my question is how do I pause the preview view and then restart it again at a later point?

this is my code

fun setupCamera(windowManager: WindowManager, previewView: PreviewView){

    _cameraProvider = _cameraProviderFuture.get()

    _preview = Preview.Builder()
        .setTargetRotation(windowManager.defaultDisplay.rotation)
        .build()

    _preview.setSurfaceProvider(previewView.previewSurfaceProvider)

    _cameraSelector = CameraSelector.Builder()
        .requireLensFacing(_requiredCameraLens)
        .build()

    _imageAnalyzer = ImageAnalysis.Builder()
        .setTargetResolution(Size(_imageWidth, _imageHeight))
        .setBackpressureStrategy(_imageBackpressureStrategy)
        .build()

    _imageAnalyzer.setAnalyzer(_imageExecutor,_analyzer)

    startPreview()

    _cameraProvider.bindToLifecycle(_lifecycleOwner, _cameraSelector, _imageAnalyzer)
}

// Called after image processing has finished
fun startPreview(){
    _cameraProvider.bindToLifecycle(_lifecycleOwner, _cameraSelector, _preview)
}

// Called when object is detected in an image
fun stopPreview(){
    _cameraProvider.unbind(_preview)
}

Solution

  • I didn't test my solution in Kotlin but it's working fine in Java. Indeed if you just call cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview) it will not really rebind your preview. In fact you have to recreate a preview and to reset the surface provider. For instance in Java when I want to rebind my preview I use:

    public void rebindPreview(){
        Preview preview = new Preview.Builder()
                .setTargetName("Preview")
                .build();
        preview.setSurfaceProvider(previewView.getPreviewSurfaceProvider());
        Camera camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);
    }
    

    I assume that for Kotlin you can do something like this:

    fun rebindPreview(){
        _preview = Preview.Builder()
                .setTargetRotation(windowManager.defaultDisplay.rotation)
                .setTargetName("Preview")
                .build()
        _preview.setSurfaceProvider(previewView.previewSurfaceProvider)
        _cameraProvider.bindToLifecycle(_lifecycleOwner, _cameraSelector, _preview)
    }