13

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

J.M.
  • 691
  • 3
  • 7
  • 15

2 Answers2

23

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);
    }
}
MrOnyszko
  • 847
  • 9
  • 13
  • when I use this the size of the preview changes... how can I prevent this? – Andrey Solera Jul 30 '17 at 02:27
  • Check if your texture view gives the same dimensions because at reopenCamera method this is set again. – MrOnyszko Jul 30 '17 at 07:09
  • I followed your code but its not wotking for me.I saw in documentation for camera2 in "setUpCameraOutputs" method `Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) { continue; }` So i removed this condition but still its not working.i followed [this](https://github.com/googlesamples/android-Camera2Basic) – Rishikesh pathak Aug 18 '17 at 06:37
  • CameraDevice throws exception while switching too fast. – Debdeep Aug 22 '17 at 12:03
14

After looking at MrOnyszko answer i followed a slightly different approach:

In the Camera2Basic Tutorial a lens facing direction is used to set up the right camera, so i changed this direction before closing and reopening the camera.

private void switchCamera() {
    if (mCameraLensFacingDirection == CameraCharacteristics.LENS_FACING_BACK) {
        mCameraLensFacingDirection = CameraCharacteristics.LENS_FACING_FRONT;
        closeCamera();
        reopenCamera();

    } else if (mCameraLensFacingDirection == CameraCharacteristics.LENS_FACING_FRONT) {
        mCameraLensFacingDirection = CameraCharacteristics.LENS_FACING_BACK;
        closeCamera();
        reopenCamera();
    }
}

private void reopenCamera() {
    if (mTextureView.isAvailable()) {
        openCamera(mTextureView.getWidth(), mTextureView.getHeight());
    } else {
        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
    }
}


private void setUpCameraOutputs(int width, int height) {
    Activity activity = getActivity();
    CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
    try {
        for (String cameraId : manager.getCameraIdList()) {
            CameraCharacteristics characteristics
                    = manager.getCameraCharacteristics(cameraId);

            Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
            if (facing != null && facing != mCameraLensFacingDirection) {
                continue;
            }
            ...
Haggy
  • 139
  • 1
  • 6
  • best and easiest answer, if you use Camera2Basic sample code – Frank Eno Jun 27 '18 at 14:39
  • nothing change to methodd setUpcameraoutputs ? i see thats ghave logic to continue if facing lens is Front. what makes that show output from front facing camera ?? – Yudi karma Apr 25 '19 at 04:28
  • This still needs a variable: private int mCameraLensFacingDirection = CameraCharacteristics.LENS_FACING_FRONT; – IAmCoder May 01 '19 at 14:47