Camera2basic app, has very dark preview in Android 6.0 LGG3-ThrowExceptions

Exception or error:

The new API, perhaps only on LG G3, seems to have something changed.

I’m using the sample code.

On my nexus 4, the code runs perfectly, but on LGG3 updated to Android 6.0 it does not. Any ideas?

I played with the settings, but no luck, this still works fine on Nexus 4:

mPreviewRequestBuilder.set(CaptureRequest.BLACK_LEVEL_LOCK, false);

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, false);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO);

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, false);

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
//mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range.create(1000,1000));
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, 0);

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, CaptureRequest.CONTROL_MODE_AUTO);


How to solve:

FPS range for Camera2 API seems to use another scale than one for older Camera API. So, if you are receiving supported preview fps range (0, 30000), you should set the values divided by 1000:

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range.create(0, 30));

Try if this helps, as it helped with older Camera API.


I’ve found the solution that work for me. The solution is to setup FPS range that supported by device.

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, getRange());

Function to get range:

private Range<Integer> getRange() {
    CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(mCameraId);
    Range<Integer>[] ranges = chars.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);

    Range<Integer> result = null;

    for (Range<Integer> range : ranges) {
        int upper = range.getUpper();

        // 10 - min range upper for my needs
        if (upper >= 10) {
            if (result == null || upper < result.getUpper().intValue()) {
                result = range;

    if (result == null) {
        result = ranges[0];

    return result;

Update: other settings (if someone interested in)

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, false);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewRequestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, CameraMetadata.STATISTICS_FACE_DETECT_MODE_SIMPLE);


Setting the proper CONTROL_AE_TARGET_FPS_RANGE is the key.

There are few reasons why this can go wrong.
As @Anton Malyshev said, some device gives you the CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES multiplied by 1000. So you must divide it by 1000 when setting CONTROL_AE_TARGET_FPS_RANGE.

Another reason I figured out is that the auto exposure fails for higher FPS depending on the resolution. So a simple workaround I did was to set the lower range to 0.

For example if the CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES has 24000:24000,
then after dividing and setting the lower value to 0, the range would be 0:24

Leave a Reply

Your email address will not be published. Required fields are marked *