Android Camera2 API switch back - front cameras

2020-02-26 08:48发布

问题:

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

回答1:

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);
    }
}


回答2:

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;
            }
            ...