29

The built in Camcorder App (like the one on the HTC EVO) seems to call camera.autoFocus() only when the preview image changes. If you hold the camera steady no camera.autoFocus() happens.
I would like to duplicate this behavior while camera.startPreview() is active as in the initial preview setup code below:

camera = camera.open();
Camera.Parameters parameters = camera.getParameters();
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
{
    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
camera.startPreview();

All the examples I found for autoFocus() seem to be calling it every 500ms to 2000ms, or once the instant before the picture is taken or recording is started.
The EVO Camcorder app seems to use a sensor or an algorithm to trigger autoFocus(). However this autoFocus() trigger is done it works exceptionally well. Does anyone have any knowledge of how to trigger autoFocus() on demand when it is needed, such as when the camera is moved close or farther from the subject or is panned slightly? Thank you, Gerry

Sarkis
  • 303
  • 2
  • 12
GerryL
  • 299
  • 1
  • 3
  • 5

5 Answers5

23

Android has introduced continuous auto focus since API Level 9 (Gingerbread). It works better than calling Camera.autoFocus periodically.

arsalank2
  • 1,683
  • 1
  • 16
  • 25
  • 2
    Continuous auto focus is not supported on some HTC devices even with API >9. Use parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO) to check whether it is supported. – d2vid Sep 25 '14 at 06:44
  • @d2vid, this is true. I developing on an API 15 HTC and it does not support continuous auto focus! – Johnny Dec 17 '14 at 00:04
  • Writing from 2018 - no, Android auto focus doesn't work better than polling autoFocus periodically on most devices, especially on close objects. – cyberj0g Jun 21 '18 at 08:03
19

I had the same problem in one of my applications.

My solution was to use a sensor listener and do auto focus when the user shook the device to some threshold. Here is the code.

public void setCameraFocus(AutoFocusCallback autoFocus){
if (mCamera.getParameters().getFocusMode().equals(mCamera.getParameters().FOCUS_MODE_AUTO) ||
        mCamera.getParameters().getFocusMode().equals(mCamera.getParameters().FOCUS_MODE_MACRO)){
    mCamera.autoFocus(autoFocus);
}

}

The callback for auto focus:

// this is the autofocus call back
private AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback(){

    public void onAutoFocus(boolean autoFocusSuccess, Camera arg1) {
        //Wait.oneSec();
        mAutoFocus = true;
    }};

And the way to call the focus.

public void onSensorChanged(SensorEvent event) {

if (mInvalidate == true){
    mView.invalidate();
    mInvalidate = false;
}
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
if (!mInitialized){
    mLastX = x;
    mLastY = y;
    mLastZ = z;
    mInitialized = true;
}
float deltaX  = Math.abs(mLastX - x);
float deltaY = Math.abs(mLastY - y);
float deltaZ = Math.abs(mLastZ - z);

if (deltaX > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing)
    mAutoFocus = false;
    mPreview.setCameraFocus(myAutoFocusCallback);
}
if (deltaY > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing)
    mAutoFocus = false;
    mPreview.setCameraFocus(myAutoFocusCallback);
}
if (deltaZ > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing) */
    mAutoFocus = false;
    mPreview.setCameraFocus(myAutoFocusCallback);
}

mLastX = x;
mLastY = y;
mLastZ = z;

}

You can see the complete project here: http://adblogcat.com/a-camera-preview-with-a-bounding-box-like-google-goggles/

Juan Acevedo
  • 1,768
  • 2
  • 20
  • 39
  • 2
    `if (mAutoFocus && (deltaX > .5 || deltaY > .5 || deltaZ > .5))` would also do nicely – Nacho Coloma Jun 04 '13 at 14:40
  • Hi, I am using surface texture not surface holder and I want to know how can I pass autofocus call back to the function? `Reader class which calls camera API` `Camera c1 = Camara(width, height, context,texture);` `//Camera class has implmentation of camera feature` `c1.setCameraFocus(); //I can add it here but how can I pass callback because it is mentioned in the camera class it self.` ` – Vishwesh Soni Aug 26 '21 at 18:12
2

It is very possible to call a refocus with a simpler technique, if you have a white box flash within the cameras view (from code, not a real box) it will rapidly call a refocus. I own the EVO 4G and one of the previous posters is correct, it does continually refocus without the need to change what it is looking at ever since the update to Gingerbread.

2

For taking pictures, you can set this.

Applications can call autoFocus(AutoFocusCallback) in this mode. If the autofocus is in the middle of scanning, the focus callback will return when it completes. If the autofocus is not scanning, the focus callback will immediately return with a boolean that indicates whether the focus is sharp or not. The apps can then decide if they want to take a picture immediately or to change the focus mode to auto, and run a full autofocus cycle.

Santosh
  • 13,251
  • 5
  • 24
  • 12
0

i would make use of the SensorEventListener. All you would need to do is to listen to sensor events and fire the autofocus once the phones orientation has changed by a sufficient threshhold.

http://developer.android.com/reference/android/hardware/SensorEventListener.html

Renard
  • 6,909
  • 2
  • 27
  • 23