androidcameracamera2android-camera2

Android Camera2 API switch back - front cameras


I'm creating a custom camera capturing videos with the new camera2 API.

My code is strongly inspired from the code provided by Google here. My camera preview has a button to switch from back to front camera and then from front to back camera. The "camera preview" activity is launched with the back camera by default.

For some reason, when I click on the "switch/swap camera" button for the first time, it brings be to the front camera as it should, BUT everytime I click again, the switch/swap doesn't work anymore: the preview (on the front camera) fades a little bit, like if something is happening, but it remains on the currently selected (front) camera.

Here is my code :

In a RecordVideoFragment, in the onViewCreated:

//  Switch camera button
        switchCameraButton = (ImageButton) view.findViewById(R.id.button_switch_camera);
        // Listener for Switch cameras button
        switchCameraButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switchCameras();
            }
        });

And here is the switchCameras() function:

private void  switchCameras() {
        mCameraOpenCloseLock.release();
        mCameraDevice.close();

        CameraManager mCameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
        try {
            String mCameraId = mCameraManager.getCameraIdList()[0];
            if (mCameraId.equals("0")) {   // If currently on FRONT camera (0 = CameraCharacteristics.LENS_FACING_FRONT)
                mCameraId = "1";           // switch to BACK camera (1 = CameraCharacteristics.LENS_FACING_BACK)
                switchCameraButton.setImageResource(R.drawable.ic_camera_front);
            } else {  // If currently on BACK camera
                mCameraId = "0"; // switch to front camera
                switchCameraButton.setImageResource(R.drawable.ic_camera_back);
            }
            try {
                if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
                        == PackageManager.PERMISSION_GRANTED) {
                    mCameraManager.openCamera(mCameraId, mStateCallback, null);
                } else {
                    requestVideoPermissions();
                }
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        } catch (CameraAccessException e) {
            Toast.makeText(getActivity(), "Cannot access the camera.", Toast.LENGTH_SHORT).show();
            getActivity().finish();
        }
    }

If you have any idea on what's happening that would save me. I have been bugging on this for days. Thank you very much


Solution

  • What you need to do is introduce new variables:

    public static final String CAMERA_FRONT = "1";
    public static final String CAMERA_BACK = "0";
    
    private String cameraId = CAMERA_BACK;
    

    remove cameraId local variable from openCamera method.

    public void switchCamera() {
        if (cameraId.equals(CAMERA_FRONT)) {
            cameraId = CAMERA_BACK;
            closeCamera();
            reopenCamera();
            switchCameraButton.setImageResource(R.drawable.ic_camera_front);
    
        } else if (cameraId.equals(CAMERA_BACK)) {
            cameraId = CAMERA_FRONT;
            closeCamera();
            reopenCamera();
            switchCameraButton.setImageResource(R.drawable.ic_camera_back);
        }
    }
    
    public void reopenCamera() {
        if (mTextureView.isAvailable()) {
            openCamera(mTextureView.getWidth(), mTextureView.getHeight());
        } else {
            mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
        }
    }