Skip to content

Instantly share code, notes, and snippets.

@gregkorossy
Last active February 10, 2021 10:20
Show Gist options
  • Save gregkorossy/364dd12b105fdc28a0b6 to your computer and use it in GitHub Desktop.
Save gregkorossy/364dd12b105fdc28a0b6 to your computer and use it in GitHub Desktop.
Mobile Vision API fix for accessing the private Camera instance of the CameraSource object, so that it can be used to set parameters, e.g. focus mode, flash mode, etc.
/**
* <p>Returns the supplied {@link com.google.android.gms.vision.CameraSource}'s {@link android.hardware.Camera} instance that is being used.</p>
* <p>
* If you want to set any of the camera parameters, here's an example that sets the focus mode to continuous auto focus and enables the flashlight:
* <blockquote>
* <code>
* Camera.Parameters params = camera.getParameters();
* params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
* params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
* camera.setParameters(params);
* </code>
* </blockquote>
* Note that your app might have to hold the permission {@code android.permission.FLASHLIGHT}, so put this in your manifest:
* <blockquote>
* <code>
* &lt;uses-permission android:name="android.permission.FLASHLIGHT" /&gt;
* </code>
* </blockquote>
* </p>
* <p>
* Also 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 get the camera and change its parameters.
* </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>
* <p>
* <b>DO NOT</b> set the following parameters using this instance as it might break the detectors:
* <ul>
* <li>picture size (<code>setPictureSize(...)</code>)</li>
* <li>preview size (<code>setPreviewSize(...)</code>)</li>
* <li>preview FPS range (<code>setPreviewFpsRange(...)</code>)</li>
* <li>preview format (<code>setPreviewFormat(...)</code>)</li>
* <li>rotation (<code>setRotation(...)</code>)</li>
* </ul>
* </p>
*
* @param cameraSource The CameraSource built with {@link com.google.android.gms.vision.CameraSource.Builder}.
* @return the actual {@link android.hardware.Camera} instance used by the supplied {@link com.google.android.gms.vision.CameraSource}, or {@code null} on failure.
* @see android.hardware.Camera
*/
public static Camera getCamera(@NonNull CameraSource cameraSource) {
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) {
return camera;
}
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
return null;
}
@jianleon
Copy link

Could you please tell me how to adapt this to the example project?
I'm just learning android.

@gregkorossy
Copy link
Author

See my last comment here with the sample code. There is MultiTrackerActivity.cameraFocus(...), you can access the raw camera instance using this code here.

Assuming you have this method in your MultiTrackerActivity class declared, you would want to change the MultiTrackerActivity.cameraFocus(mCameraSource, Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); row to Camera camera = MultiTrackerActivity.getCamera(mCameraSource);. Then, you can set parameters on this camera instance. See the javadoc (the comment section above the actual code) where I put an example of setting the focus mode to continuous auto focus and the flash mode to torch (which means that your device's flash will turn on) using the acquired camera object.

@sudipidus
Copy link

Following is my CameraSource object.

cameraSource = new CameraSource.Builder(context, detector)
                .setRequestedPreviewSize(640, 480)
                .setFacing(camId)
                .setRequestedFps(30.0f)
                .build();

it's always returning null for me. What am I doing wrong?

@anroswart
Copy link

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

@ojocampof
Copy link

Thanks! Works pretty cool

@gregkorossy
Copy link
Author

What do you mean? You want to make an IP camera app?

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