Provided camera selector unable to resolve a camera for the given use case
Asked Answered
D

4

7

I use camera in compose to take picture. Code for camera preview^

@Composable
fun CameraPreview(
    modifier: Modifier = Modifier,
    scaleType: PreviewView.ScaleType = PreviewView.ScaleType.FILL_CENTER,
    onUseCase: (UseCase) -> Unit = { }
) {
    AndroidView(
        modifier = modifier,
        factory = { context ->
            val previewView = PreviewView(context).apply {
                this.scaleType = scaleType
                layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
            }
            onUseCase(
                Preview.Builder()
                .build()
                .also {
                    it.setSurfaceProvider(previewView.surfaceProvider)
                }
            )
            previewView
        }
    )
}

Code for take picture

@Composable
fun CameraCapture(
    modifier: Modifier = Modifier,
    cameraSelector: CameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA,
    onPhotoCreated: (Bitmap, String) -> Unit = { bitmap, string ->  bitmap; string},
    onClose: () -> Unit,
    onFullScreen: (Boolean) -> Unit = {},
    systemUiController: SystemUiController = rememberSystemUiController()
) {
    var isFullScreen by remember { mutableStateOf(true) }

    onFullScreen(isFullScreen)
    WindowCutoutMode(isFullScreen = isFullScreen)
    SystemBarColor(
        systemUiController = systemUiController,
        specialStatusColor = Color.Transparent
    )

    Box(modifier = modifier) {
        val context = LocalContext.current
        val lifecycleOwner = LocalLifecycleOwner.current
        var previewUseCase by remember { mutableStateOf<UseCase>(Preview.Builder().build()) }

        CameraPreview(
            modifier = Modifier.fillMaxSize(),
            onUseCase = {
                previewUseCase = it
            }
        )

        var newSelector by remember { mutableStateOf(cameraSelector) }

        val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
        val cameraProvider = cameraProviderFuture.get()

        val cameraExecutor: ExecutorService = Executors.newSingleThreadExecutor()

        val imageCaptureUseCase by remember {
            mutableStateOf(
                ImageCapture.Builder()
                    .setCaptureMode(CAPTURE_MODE_MAXIMIZE_QUALITY)
                    .build()
            )
        }
        val coroutineScope = rememberCoroutineScope()

        Box(
            modifier = Modifier
                .align(Alignment.TopStart)
                .padding(top = 48.dp, start = 16.dp)
                .clip(CircleShape)
                .background(Colors.Background.transparent)
        ) {
            Icon(
                imageVector = Icons.Rounded.Close,
                contentDescription = null,
                modifier = Modifier
                    .clickable(
                        role = Role.Button
                    ) {
                      isFullScreen = false
                      onClose()
                    },
            )
        }

        Row(
            modifier = Modifier
                .fillMaxWidth()
                .background(Colors.Background.light)
                .align(Alignment.BottomCenter),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            GalleryImagePicker(onPhotoCreated)

            Box(
                modifier = Modifier
                    .size(100.dp)
                    .padding(16.dp)
                    .clip(CircleShape)
                    .background(Color.White),
            ) {
                Box(
                    modifier = Modifier
                        .size(80.dp)
                        .padding(5.dp)
                        .clickable(
                            role = Role.Button
                        ) {
                            coroutineScope.launch(Dispatchers.IO) {
                                val imageFile = imageCaptureUseCase.takePicture(cameraExecutor)
                                onPhotoCreated(rotateByOrientation(imageFile), imageFile.name)
                            }
                        }
                        .clip(CircleShape)
                        .background(Color.Black),
                ) {

                }
            }

            Box(
                modifier = Modifier
                    .size(80.dp)
                    .padding(16.dp)
                    .clip(CircleShape)
                    .background(Color.White),
            ) {
                Box(
                    modifier = Modifier
                        .size(60.dp)
                        .padding(5.dp)
                        .clip(CircleShape)
                        .background(Color.Black),
                ) {
                    Icon(
                        imageVector = ImageVector.vectorResource(id = R.drawable.ic_camera_change),
                        contentDescription = "",
                        tint = Color.White,
                        modifier = Modifier
                            .align(Alignment.Center)
                            .clickable(
                                role = Role.Button
                            ) {
                                newSelector =
                                    if (newSelector == CameraSelector.DEFAULT_FRONT_CAMERA)
                                        CameraSelector.DEFAULT_BACK_CAMERA
                                    else
                                        CameraSelector.DEFAULT_FRONT_CAMERA
                            }
                    )
                }
            }
        }

        LaunchedEffect(newSelector) {
            try {
                cameraProvider.unbindAll()
                cameraProvider.bindToLifecycle(
                    lifecycleOwner,
                    newSelector,
                    previewUseCase,
                    imageCaptureUseCase
                )
            } catch (ex: Exception) {
                Log.e("CameraCapture", "Failed to bind camera use cases", ex)
            }
        }
    }
}

The code works fine all time, but suddenly (on this week) it started to thorws an exceptions like java.lang.IllegalArgumentException: Provided camera selector unable to resolve a camera for the given use case with message Failed to bind camera use cases. When view opens it has only black screen. The code didn't changes and i can't see the error.

Versions:

"androidx.camera:camera-core:1.0.1""
"androidx.camera:camera-camera2:1.0.1""
"androidx.camera:camera-lifecycle:1.0.1""
"androidx.camera:camera-view:1.1.0-beta02"
"androidx.camera:camera-extensions:1.1.0-beta02"

UPDATE

Some more exceptions from log:

Camera LensFacing verification failed, existing cameras: []
CameraValidator$CameraIdListIncorrectException: Expected camera missing from device.

UPDATE 2

After device reboot exception gone, but preview is black screen and it spam every second log messages like

D/Camera2CameraImpl: {Camera@739281d[id=1]} Transitioning camera internal state: OPENED --> CLOSING

Disparate answered 12/5, 2022 at 14:8 Comment(2)
were you able to fix this issue? I am facing similar one.Distillery
Are you testing this on an emulator or a physical device?Illuminati
I
5

I had a similar issue on an emulator in my case, to resolve it I needed to change the camera settings in the Virtual Device Configuration (AVD) under show advanced settings of the device from Virtual Scene to Emulated on the back camera.

Camera settings

Illuminati answered 12/4, 2023 at 9:9 Comment(0)
F
2

In my case, it was because I was requesting front and back camera simultaneously and my device doesn't have both cameras.

val cameraSelector: CameraSelector = CameraSelector.Builder()
    .requireLensFacing(CameraSelector.LENS_FACING_BACK)
    .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
    .build()

The fix was very simple, just check if camera is available before assigning requireLensFacing :

val cameraSelector: CameraSelector = CameraSelector.Builder()
    .apply {
        if (cameraProvider.hasCamera(CameraSelector.DEFAULT_BACK_CAMERA)) {
            requireLensFacing(CameraSelector.LENS_FACING_BACK)
        } else if (cameraProvider.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA)) {
            requireLensFacing(CameraSelector.LENS_FACING_FRONT)
        } else {
            throw IllegalArgumentException("No available cameras on the device")
        }
    }
    .build()
Felicafelicdad answered 4/11, 2023 at 15:49 Comment(0)
L
0

The permission has to be re-granted.

EDIT: Have you ensured that no other apps are using the camera at the moment? If the internal state was OPENED, maybe it is clashing with another source utilising the resource.

Languorous answered 12/5, 2022 at 20:29 Comment(3)
I already tried this and it didn't helpDisparate
I came across a similar problem with camerax, and threre were literally no log messages stating the actual problem. All that was logged was a constant loop of OPENED and CLOSED until I stopped the app. That's exactly what the question states as the problem. I know this isn't like a regular answers you'd find on SO, but in this specific case, that literally was the only thing that worked for me, so I posted here. Turned out, the permission had been removed and I had to manually re-grant it to make it work.Languorous
That's the behaviour of camerax -- if permission is denied, it goes in a loop of try/fail.Languorous
D
0

I got the same error when I was following the following tutorial

Take Photos Using the Camera with Jetpack Compose

And I was able to resolve it by changing

from

val lensFacing = CameraSelector.LENS_FACING_BACK

to

val lensFacing = CameraSelector.LENS_FACING_FRONT

so here is the difference if you want to use the front or back camera.

In my case, I got only a front camera.

Now, coming to your code above, I could see that you feed the LaunchedEffect with the newSelector that has either CameraSelector.DEFAULT_BACK_CAMERA or CameraSelector.DEFAULT_FRONT_CAMERA

But, as I've stated earlier, CameraSelector.LENS_FACING_FRONT worked for me so I think you need to change both of them to

 if (newSelector == CameraSelector.LENS_FACING_BACK)
     CameraSelector.LENS_FACING_BACK
 else
     CameraSelector.LENS_FACING_BACK
Draftsman answered 30/8, 2022 at 5:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.