11

I have the code for the Camera2 from https://github.com/googlesamples/android-Camera2Basic.

The problem i'm facing is that when i turn to my Front Camera, i cannot capture pictures but works fine with Back Camera.

Has anyone implemented the Camera2 Api please help!

Here's the code snippet:

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

            // We don't use a front facing camera in this sample.
            int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
            Log.i(TAG,"Front Cam ID: "+ facing);
            if (characteristics.get(CameraCharacteristics.LENS_FACING)==CameraCharacteristics.LENS_FACING_FRONT)
            {



                StreamConfigurationMap map = characteristics.get(
                        CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);


                // For still image captures, we use the largest available size.
                Size largest = Collections.max(
                        Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
                        new CompareSizesByArea());
                mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(),
                        ImageFormat.JPEG, /*maxImages*/2);
                mImageReader.setOnImageAvailableListener(
                        mOnImageAvailableListener, mBackgroundHandler);

                // Danger, W.R.! Attempting to use too large a preview size could  exceed the camera
                // bus' bandwidth limitation, resulting in gorgeous previews but the storage of
                // garbage capture data.
                mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                        width, height, largest);

                // We fit the aspect ratio of TextureView to the size of preview we picked.
                int orientation = getResources().getConfiguration().orientation;
                if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    mTextureView.setAspectRatio(
                            mPreviewSize.getWidth(), mPreviewSize.getHeight());
                } else {
                    mTextureView.setAspectRatio(
                            mPreviewSize.getHeight(), mPreviewSize.getWidth());
                }

                mCameraId = cameraId;
                return;
            }
            else
            {
                onActivityCreated(Bundle.EMPTY);
            }
        }
    } catch (CameraAccessException e) {
        e.printStackTrace();
    } catch (NullPointerException e) {
        // Currently an NPE is thrown when the Camera2API is used but not supported on the
        // device this code runs.
        ErrorDialog.newInstance(getString(R.string.camera_error))
                .show(getChildFragmentManager(), FRAGMENT_DIALOG);
    }
}
Veeresh
  • 363
  • 3
  • 5
  • 9

5 Answers5

30

The problem is that many front-facing cameras have a fixed focus distance. So after the autofocus trigger in lockFocus() the autofocus state (CONTROL_AF_STATE) remains INACTIVE and the autofocus trigger does nothing.

So in order to make it work you need to check whether autofocus is supported or not. To do so, add the following to setUpCameraOutputs():

int[] afAvailableModes = characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);

if (afAvailableModes.length == 0 || (afAvailableModes.length == 1
        && afAvailableModes[0] == CameraMetadata.CONTROL_AF_MODE_OFF)) {
    mAutoFocusSupported = false;
} else {
    mAutoFocusSupported = true;
}

Finally don't lock focus if its not supported when you want to take a picture:

private void takePicture() {
    if (mAutoFocusSupported) {
        lockFocus();
    } else {
        captureStillPicture();
    }
}
D-rk
  • 5,513
  • 1
  • 37
  • 55
13

For Camera2 Api, Google's example for video works great for both front and back camera, but for Image capturing, Google's example works only for back camera and not for front camera.
Solution which works for me is

In lockFocus() method, replace line

mCaptureSession.capture(mPreviewRequestBuilder.build(),
                                                  mCaptureCallback, mBackgroundHandler);

with

captureStillPicture();

Hope this will help!!

Subin Chalil
  • 3,531
  • 2
  • 24
  • 38
Arvind Singh
  • 139
  • 4
  • 1
    Hai this is working fine !! but the captured image is rotated 180 degree ,Any solution for this issue ?? – Jack Feb 19 '16 at 05:42
  • @jaxon : You will have to rotate the image based on the device. I think the google examples have this in the code. – dotfury Mar 05 '16 at 00:26
  • 1
    In CaptureStillPicture() method, Replace int rotation = getWindowManager().getDefaultDisplay().getRotation(); captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); lines with captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)); This will solve your problem accross all devices with Android>=5.0 – Arvind Singh Mar 07 '16 at 06:06
  • @Arvind Singh :Thanx for the reply , I tried this but still no change in the output , – Jack Mar 08 '16 at 12:41
  • and i have solved the rotation issue by changing the ORIENTATIONS.get(rotation) with integer value 270 -- captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, 270); like this – Jack Mar 08 '16 at 12:51
  • But now the problem is ,the output image is looks like a mirror image ..Hope you understood .Can you help me to solve this issue? – Jack Mar 08 '16 at 12:53
  • //Let's assume bitmap is the generated one from camera(Mirror Image) Matrix matrix = new Matrix(); matrix.preScale(-1, 1); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); bitmap.setDensity(DisplayMetrics.DENSITY_DEFAULT); //now the bitmap is converted into unmirrored bitmap – Arvind Singh Mar 09 '16 at 17:45
  • For the rotated image produced, the solution suggested by me works for me .The solution suggested by you may work on some devices and some not. So please test on devices with different manufactures.Hope this will help you :) – Arvind Singh Mar 09 '16 at 17:50
  • In my case I needed to add the code suggested because of the try and catch block. Worked fine... I just needed to adjust the orientation with this command: mImageView.setRotation(270); – Marcelo Gumiero Jan 30 '17 at 20:35
  • I had problem with image capturing even with front camera in some phones adding this workaround solved the issue. Thanks – AbuMaaiz May 31 '19 at 09:17
  • this work for me for both front and back camera because I faced this issue on both back and front camera – user2905416 Nov 18 '19 at 04:47
4

@ArvindSingh's solution is not the best one, because you would also disable the focus functionality for the back camera. A better solution would be to do a camera facing check inside the takePicture like that:

private void takePicture() {
    if (CameraCharacteristics.LENS_FACING_FRONT == mSelectedFacing) {
        // front camera selected, so take a picture without focus
        captureStillPicture();
    } else {
        // back camera selected, trigger the focus before creating an image
        lockFocus();
    }
}

For this solution you only need to save the current used facing somewhere like here in mSelectedFacing

0xPixelfrost
  • 10,244
  • 5
  • 39
  • 58
1

In lockFocus() method, replace line

mCaptureSession.capture(mPreviewRequestBuilder.build(),
                                              mCaptureCallback,    mBackgroundHandler);

with

captureStillPicture();

And to prevent Unwanted orientation you can use

/** * Conversion from screen rotation to JPEG orientation. */

   static {
       ORIENTATIONS.append(Surface.ROTATION_0, 270);
       ORIENTATIONS.append(Surface.ROTATION_90, 0);
       ORIENTATIONS.append(Surface.ROTATION_180, 180);
       ORIENTATIONS.append(Surface.ROTATION_270, 270);
   }
Getaw Dejen
  • 341
  • 1
  • 4
  • 13
-1

Plz try this code for capture

case STATE_WAITING_LOCK: {
                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                if (afState == null) {
                    captureStillPicture();
                } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                        CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState ||
                         CaptureResult.CONTROL_AF_STATE_INACTIVE == afState /*add this*/) {
                    // CONTROL_AE_STATE can be null on some devices
                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                    if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                        mState = STATE_PICTURE_TAKEN;
                        captureStillPicture();
                    } else {
                        runPrecaptureSequence();
                    }
                }
                break;
            }
Vasily Kabunov
  • 6,511
  • 13
  • 49
  • 53
Vishnu V S
  • 355
  • 1
  • 10