Search code examples
androidandroid-jetpackandroid-camerax

how to change camera lens facing programmatically in Camera X library?


currently I am using this gradle

implementation "androidx.camera:camera-camera2:1.0.0-beta11"
implementation "androidx.camera:camera-lifecycle:1.0.0-beta11"
implementation "androidx.camera:camera-view:1.0.0-alpha18"

so I want change the camera lens facing programmatically after the user tap a button. here is the code that I try to use

class CameraFragment : Fragment() {

    private var cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

    lateinit var mContext: Context
    lateinit var mActivity: FragmentActivity

    override fun onAttach(context: Context) {
        super.onAttach(context)

        mContext = context
        activity?.let { mActivity = it }

    }

    private fun toggleFrontBackCamera() {


        if (cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
            cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
        } else if (cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA) {
            cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA
        }

        startCamera()


    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(mContext)

        cameraProviderFuture.addListener(Runnable {
            // Used to bind the lifecycle of cameras to the lifecycle owner
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

            // Preview
            val preview = Preview.Builder()
                    .build()
                    .also {
                        it.setSurfaceProvider(previewView.surfaceProvider)
                    }


            imageCapture = ImageCapture.Builder().build()


            try {
                // Unbind use cases before rebinding
                cameraProvider.unbindAll()

                // Bind use cases to camera
                cameraProvider.bindToLifecycle(
                        this, cameraSelector, preview, imageCapture)

            } catch (exc: Exception) {
                Log.e(TAG, "Use case binding failed", exc)
            }

        }, ContextCompat.getMainExecutor(mContext))
    }


}

I use that toggleFrontBackCamera() method to change the lens programmatically.

as you can see, the default camera is back camera, and then when the user tap the button to change camera then toggleFrontBackCamera() method will be called for the first time, then the camera will change from Back to Front. no issue in here

but the problem is, when the user want to change the camera lens again, from front back to back camera, then toggleFrontBackCamera() will not work, it stuck in CameraSelector.DEFAULT_FRONT_CAMERA

so how to change it programmatically ?


Solution

  • Initialize a variable in the beginning:

    private var lensFacing = CameraSelector.LENS_FACING_BACK
    

    Change your camera toggle method to this:

    private fun toggleFrontBackCamera() {
        lensFacing = if (CameraSelector.LENS_FACING_FRONT == lensFacing)
            CameraSelector.LENS_FACING_BACK
        else 
            CameraSelector.LENS_FACING_FRONT
        startCamera()
    }
    

    And finally create an instance of CameraSelector in your startCamera() and use this in cameraProvider.bindToLifecycle():

    val cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()