Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Mobile Vision API fix for missing autofocus feature
/*
* IF YOU WANT TO JUST ACCESS THE CAMERA INSTANCE SO THAT YOU CAN SET ANY OF THE PARAMETERS, VISIT THE FOLLOWING LINK:
* https://gist.github.com/Gericop/364dd12b105fdc28a0b6
*/
/**
* Custom annotation to allow only valid focus modes.
*/
@StringDef({
Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
Camera.Parameters.FOCUS_MODE_AUTO,
Camera.Parameters.FOCUS_MODE_EDOF,
Camera.Parameters.FOCUS_MODE_FIXED,
Camera.Parameters.FOCUS_MODE_INFINITY,
Camera.Parameters.FOCUS_MODE_MACRO
})
@Retention(RetentionPolicy.SOURCE)
private @interface FocusMode {}
/**
* <p>
* Sets the Mobile Vision API provided {@link com.google.android.gms.vision.CameraSource}'s
* focus mode. Use {@link Camera.Parameters#FOCUS_MODE_CONTINUOUS_PICTURE} or
* {@link Camera.Parameters#FOCUS_MODE_CONTINUOUS_VIDEO} for continuous autofocus.
* </p>
* <p>
* Note that the CameraSource's {@link CameraSource#start()} or
* {@link CameraSource#start(SurfaceHolder)} has to be called and the camera image has to be
* showing prior using this method as the CameraSource only creates the camera after calling
* one of those methods and the camera is not available immediately. You could implement some
* kind of a callback method for the SurfaceHolder that notifies you when the imaging is ready
* or use a direct action (e.g. button press) to set the focus mode.
* </p>
* <p>
* Check out <a href="https://github.com/googlesamples/android-vision/blob/master/face/multi-tracker/app/src/main/java/com/google/android/gms/samples/vision/face/multitracker/ui/camera/CameraSourcePreview.java#L84">CameraSourcePreview.java</a>
* which contains the method <code>startIfReady()</code> that has the following line:
* <blockquote><code>mCameraSource.start(mSurfaceView.getHolder());</code></blockquote><br>
* After this call you can use our <code>cameraFocus(...)</code> method because the camera is ready.
* </p>
*
* @param cameraSource The CameraSource built with {@link com.google.android.gms.vision.CameraSource.Builder}.
* @param focusMode The focus mode. See {@link android.hardware.Camera.Parameters} for possible values.
* @return true if the camera's focus is set; false otherwise.
* @see com.google.android.gms.vision.CameraSource
* @see android.hardware.Camera.Parameters
*/
public static boolean cameraFocus(@NonNull CameraSource cameraSource, @FocusMode @NonNull String focusMode) {
Field[] declaredFields = CameraSource.class.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getType() == Camera.class) {
field.setAccessible(true);
try {
Camera camera = (Camera) field.get(cameraSource);
if (camera != null) {
Camera.Parameters params = camera.getParameters();
if (!params.getSupportedFocusModes().contains(focusMode)) {
return false;
}
params.setFocusMode(focusMode);
camera.setParameters(params);
return true;
}
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
return false;
}
@pm0733464

This comment has been minimized.

Copy link

@pm0733464 pm0733464 commented Aug 17, 2015

Thanks. See also the focus mode constants here:

http://developer.android.com/reference/android/hardware/Camera.Parameters.html

(e.g., supplying "continuous-video" for focusMode should work well)

@Aeefire

This comment has been minimized.

Copy link

@Aeefire Aeefire commented Aug 17, 2015

or torch flash mode?

@Gericop

This comment has been minimized.

Copy link
Owner Author

@Gericop Gericop commented Aug 18, 2015

If you want to access the camera (so that you can set the other parameters as well), use this:
https://gist.github.com/Gericop/364dd12b105fdc28a0b6

@pm0733464

This comment has been minimized.

Copy link

@pm0733464 pm0733464 commented Aug 21, 2015

Note that some devices don't support camera auto focus (hardware issue). You should probably do something like this:

if (params.getSupportedFocusModes().contains(focusMode)) {
    params.setFocusMode(focusMode);
    camera.setParameters(params);
    return true;
} else {
    // Camera auto focus is not supported on this device.
    return false;
}
@Gericop

This comment has been minimized.

Copy link
Owner Author

@Gericop Gericop commented Aug 21, 2015

Thanks for the note, updated the gist to check if the focus mode is supported.

@tundeaina

This comment has been minimized.

Copy link

@tundeaina tundeaina commented Sep 3, 2015

Thanks Gergely! cameraFocus works like a charm. I'll try using getCamera next.

@joshfischer1108

This comment has been minimized.

Copy link

@joshfischer1108 joshfischer1108 commented Sep 8, 2015

A lot of this code was deprecated in Api 21. Any fix on the way? Either way, nice work.

@Gericop

This comment has been minimized.

Copy link
Owner Author

@Gericop Gericop commented Sep 9, 2015

This is the official way Google does the camera handling (they don't use the new Camera 2 API in their code so I couldn't do it either).

@Mun0n

This comment has been minimized.

Copy link

@Mun0n Mun0n commented Sep 28, 2015

I can't get autofocus working. I'm doing something wrong for sure

CameraSource.Builder builder = new CameraSource.Builder(getApplicationContext(), barcodeDetector)
                .setFacing(CameraSource.CAMERA_FACING_BACK)
                .setRequestedPreviewSize(1600, 1024)
                .setRequestedFps(15.0f);

mCameraSource = builder.build();
cameraFocus(mCameraSource, Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);

I've also detected that the 1D barcodes are not detected since I've used this code.

Any help?

@Gericop

This comment has been minimized.

Copy link
Owner Author

@Gericop Gericop commented Sep 28, 2015

You're calling the cameraFocus(...) method before the Camera instance in the CameraSource object is initialized. After you call mCameraSource.start(...), you should be good. Here's the sample project's CameraSourcePreview's startIfReady() method as an example:

private void startIfReady() throws IOException {
    if (mStartRequested && mSurfaceAvailable) {
        mCameraSource.start(mSurfaceView.getHolder());
        MultiTrackerActivity.cameraFocus(mCameraSource, Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        // [...]
    }
}

Note that the latest sample open sources the CameraSource class and its Builder has a setFocusMode(...) method that can be used instead of my temporary bugfix with reflection.

@Mun0n

This comment has been minimized.

Copy link

@Mun0n Mun0n commented Sep 29, 2015

Thanks for the response. I don't understand. Everything is working fine except in some Samsung devices like SM-N9005. It doesn't detect anything, even using the demo app from google. Any idea?

@Gericop

This comment has been minimized.

Copy link
Owner Author

@Gericop Gericop commented Sep 29, 2015

Are those devices connected to the Internet? Did you check if the detector isOperational()?

@hendrawd

This comment has been minimized.

Copy link

@hendrawd hendrawd commented Nov 19, 2015

I was searching how to show line focus like zxing library to google camera API and got here. I little bit confused at first and think that this gist is still valid. Can you update the gist description, since the new example already have setFocusMode? It will be useful to inform the other users that got here without reading the comments or trying to implement the code. Thank you

@anroswart

This comment has been minimized.

Copy link

@anroswart anroswart commented Jan 13, 2017

.setAutoFocusEnabled(true) does not work although my device has auto focus. http://stackoverflow.com/questions/41629911/

@sarimo1

This comment has been minimized.

Copy link

@sarimo1 sarimo1 commented Apr 7, 2017

where can i add this code gyus . i'm a biginer
please tell me

@nguyenthao1988

This comment has been minimized.

Copy link

@nguyenthao1988 nguyenthao1988 commented Aug 28, 2017

how to use file VisionApiFocusFix.java. Please share source scan qr code with mobile vision with fixed auto camera focus. Thanks all!

@ivanschuetz

This comment has been minimized.

Copy link

@ivanschuetz ivanschuetz commented Feb 27, 2018

This isn't necessary anymore... or am I missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment