How to use autofocus in Android


I’m having Android G1 device and while I’m doing the photos with integrated camera software I see that device is trying to focus before taking the photos (I hear the beep and see green border after camera is focused)
But here is the issue – how to focus the camera using the Android API from you android application ?
In the book “Professional Application Android Development” I’ve found only short example about using camera and it doesn’t use any autofocus features of the device/API. (see chapter 10 “Accessing Android Hardware”/”Using Camera”). It is actually an entry point but not the solution to take good pictures (I must admit it’s quite optimistic to say that G1 could make photos with good quality – probably only in a sunny day. But again – it will never be even close to the photos from Nokia N82)
CameraPreiew class (com.example.android.apis.graphics package) from the API-Examples shows only the way to start activity with preview from camera.

The key here is to call camera.autoFocus(autoFocusCallBack) and after we focused method autofocusCallback.onAutoFocus(boolean success, Camera camera) is called – call the camera.takePicture (Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg)

here is the example code (take a notice that everything here is happen inside onKeyDown event handler)

public final boolean onKeyDown(int keyCode, KeyEvent event) {
synchronized(this) {
    if (!bIsPictureTaking) {
        //we care only about two buttons here
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_CAMERA) {
            //that method support tow modes with and without autofocus
            if (USE_AUTOFOCUS){
                //autofocus mode
                if (!bIsPictureTaking && !bIsAutoFocusStarted){
                    //start autofocus if it was-not started
                    AutoFocusCallBackImpl autoFocusCallBack = new AutoFocusCallBackImpl();
                    cDevice.autoFocus(autoFocusCallBack);
                    //set the bIsAutoFocusStarted trigger to false to avoid extra autofocus attempts
                    bIsAutoFocusStarted = true;
                    return true;
                }

                long autoFocusTime = event.getEventTime() - event.getDownTime();
                //autoFocusTime is the time we spent in the autofocusing
                boolean isAutofocusTimeout = (bIsAutoFocusStarted && autoFocusTime > AUTOFOCUS_TIME_LIMIT_MILISECONDS);
                if (bIsAutoFocused){
                    Log.i(TAG, "Autofocused, taking picture. Autofocus time="+autoFocusTime+" ms");
                } else if (isAutofocusTimeout){
                    Log.i(TAG, "Autofocus timeout reached, taking picture. time for focus is:"+autoFocusTime+" ms");
                }

                if (bIsAutoFocused || isAutofocusTimeout){
                    //if camera got focused or we have autofocus-timeout - take the picture (we will never be focused in the darkness)
                    takePicture();
                }
            } else {
                //non-autofocus mode, nothing special just take the picture
                takePicture();
            }
        }

        //support for the BACK button to exit from activity
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            setResult(LifecycleConstants.CAMERA_CANCELLED);
            return super.onKeyDown(keyCode, event);
        }
    }
}
return true;
}

private class AutoFocusCallBackImpl implements Camera.AutoFocusCallback {
    @Override
    public void onAutoFocus(boolean success, Camera camera) {
        bIsAutoFocused = success; //update the flag used in onKeyDown()
        Log.i(TAG, "Inside autofocus callback. autofocused="+success);
        //play the autofocus sound
        MediaPlayer.create(CameraActivity.this, R.raw.auto_focus).start();
    }
}

private void takePicture(){
    bIsPictureTaking = true;  //set it to true to avoid onKeyDown dispatching during taking picture. it may be time-consuming
    bIsAutoFocused = false; //reset to false
    bIsAutoFocusStarted = false; //reset to false

    //create the file to write output content (picture) to
    String fileName = myDateFormat.format(new Date()).concat(".jpg");
    ContentValues values = new ContentValues();
    values.put(Media.TITLE, fileName);
    values.put(Media.DESCRIPTION, "Image capture by camera");
    Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
    OutputStream os = null;
    try {
         os = (FileOutputStream) getContentResolver().openOutputStream(uri);
    } catch (Exception ex) {
        Logger.getLogger("CameraActivity").log(Level.WARNING,"Failed to take Picture", ex);
        setResult(LifecycleConstants.CAMERA_FAILED_TO_TAKE_PHOTO);
        finish();
        return;
    }

    //create ImageCaptureCallback and pass output stream to it
    ImageCaptureCallback iccb = new ImageCaptureCallback(os, uri.toString());

    //you also could add shuter callback to play sound for example
    cDevice.takePicture(null, null, iccb);
    findViewById(R.id.surface).setVisibility(View.INVISIBLE);
    findViewById(R.id.SavingPhotoPanel).setVisibility(View.VISIBLE);
}

private class ImageCaptureCallback implements PictureCallback {

private OutputStream foStream;
private final String sFileName;

public ImageCaptureCallback(OutputStream filoutputStream, String fileName) {
    this.foStream = filoutputStream;
    this.sFileName = fileName;
}

@Override
public void onPictureTaken(byte[] data, Camera camera) {
    boolean exception = false;
    //write image and close output-stream
    try {
        foStream.write(data);
        foStream.flush();
    } catch (Exception ex) {
        exception = true;
        android.util.Log.v(getClass().getSimpleName(), "Error while taking photo", ex);
        ex.printStackTrace();
    } finally {
        if (foStream != null){
            try {
                foStream.close();
            } catch (Exception ex){
                android.util.Log.v(getClass().getSimpleName(), "Error while taking photo", ex);
                ex.printStackTrace();
            }
        }
    }

    //pass the information back to the caller-activity via Intent with Bundle (intent.putExtras(bundle))
    Bundle bundle = new Bundle();
    if (sFileName != null) {
        //set the file-name property, so caller activity will be able to resolve the file to which picture was written to
        bundle.putString(LifecycleConstants.PHOTO_URI, sFileName);
    }
    Intent intent = new Intent();
    intent.putExtras(bundle);
    setResult(exception ? LifecycleConstants.CAMERA_FAILED_TO_TAKE_PHOTO : LifecycleConstants.CAMERA_PHOTO_TAKEN, intent);
    finish();
}
}

It’s the description of my short experience with Android autofocus, if you are interested in that topic you could explore ZXing library (which is actually scan Bar-Codes and QR-Codes but it also use autofocus inside //continuous autofocus)
and the very interesting ideas could be found in the “Snap Photo Pro” for Android, that software uses the accelerometer to stabilize the image. it also has the white-balance and other features. But it’s not an open-source, it’s a paid software. It would be very interesting to know how image-stabilization is implemented and I think it would be very useful component if they will make their software available as a component (like ZXing) which you can use/integrate with your application via Intent/Activity

    Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
    activity.startActivityForResult(intentScan, requestCode);

https://www.facebook.com/achorniy

Tagged with: , , ,
Posted in Software Development, Tips and Tricks
22 comments on “How to use autofocus in Android
  1. BestKirdApe says:

    I luv this tutorial on autofocus. 😀

  2. Fernando says:

    Thanks man, that example is great!!!!!!

  3. […] If you want to use possible autofocus, you can take a look over here […]

  4. sara says:

    I just got a droid and I am looking for an application to turn off the autofocus when I want to take pictures of my son. He is 2 and does not sit still long enough for the auto focus to do its thing before taking the picture! Please help!

  5. Name says:

    I wish you shared whole code!

    • Andrey Chorniy says:

      I actually don’t have the separate example for that (it’s integrated with the project) but will try to create simple demo-app

  6. aqoerama says:

    hi.. i have a problem with my x10 mini pro, i guess this question is off topic.. but it seems like my autofocus feature is gone.. was unsatisfied. so i would like to ask, is there any app that can show extra info about my camera, i mean, the condition of the hardware itself, because i want to know what cause the auto focus feature gone. thanks

  7. hantran says:

    Can I ask a question?
    I’m a newbie, I don;t understand about line:

    long autoFocusTime = event.getEventTime() – event.getDownTime();

    “event” <— what is this? And how can I use it in my code?

    • Andrey Chorniy says:

      it’s about following parameter
      public final boolean onKeyDown(int keyCode, KeyEvent event) {

      • hantran says:

        Okay, see! So if I use
        private OnClickListener capture_click= new OnClickListener()

        so how I can get the autoFocusTime ?

  8. hantran says:

    Okay, see! So if I use
    private OnClickListener capture_click= new OnClickListener()

    so how I can get the autoFocusTime ?

    Please help me! 😦

  9. priyanka says:

    hi..
    this code is really very useful to me…
    please can you share complete code..

  10. priyanka says:

    can you please share complete code..its very urgent to me.

  11. good advice says:

    My brother recommended I may like this blog.
    He was totally right. This post truly made my day.
    You can not imagine just how a lot time I had spent for this information!
    Thank you!

  12. When some one searches for his required thing, so he/she needs to be available that in detail, so that
    thing is maintained over here.

  13. Hmm is anyone else having problems with the images on
    this blog loading? I’m trying to determine if its
    a problem on my end or if it’s the blog. Any feed-back would be greatly appreciated.

  14. List those achievable reasons and attempt to stay
    away from it. Costly manicures and also fingernail
    paints dishearten folk from biting their particular unique nails You must
    utilize a high-quality and also fancy fingernail distribute which will render this work better.
    Here are a variety of remedies that show you how to repel ticks naturally.

  15. hello there
    my phone is 8 megapixl but not autofocus
    what to do to make auto fucus ???

Leave a comment