android – autoFocus throwing exception-ThrowExceptions

Exception or error:

I have tried everything but I’m still unable to solve this issue.

I am implementing a camera feature in an app and everything works fine except the autofocus. When I call autoFocus(), it throws an exception, and I can’t understand why. I am running the code on a Desire HD.

Code:

@Override
protected void onStart() {
     super.onStart();

     //grab seurface view and callback
     cameraView = (CameraSurfaceView) findViewById(R.id.cameraView);
     try{
        camera = Camera.open();
        cameraView.setCamera(camera);
        //release previous autofocus and assign new one
        camera.cancelAutoFocus();
        camera.autoFocus(new Camera.AutoFocusCallback() {

                public void onAutoFocus(boolean success, Camera camera) {
                // TODO Auto-generated method stub

                }});
    }
    catch (Exception e) {
        //had an issue accessing the camera prompt user
        //TODO create user prompt
        e.printStackTrace();
    }
}

Stack trace:

01-11 16:09:38.456: W/System.err(26546): java.lang.RuntimeException: autoFocus failed
01-11 16:09:38.456: W/System.err(26546):    at android.hardware.Camera.native_autoFocus(Native Method)
01-11 16:09:38.456: W/System.err(26546):    at android.hardware.Camera.autoFocus(Camera.java:680)
01-11 16:09:38.456: W/System.err(26546):    at com.myapp.MyActivity.onStart(BarcodeScannerActivity.java:57)
01-11 16:09:38.466: W/System.err(26546):    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1201)
01-11 16:09:38.466: W/System.err(26546):    at android.app.Activity.performStart(Activity.java:3955)
01-11 16:09:38.466: W/System.err(26546):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1845)
01-11 16:09:38.466: W/System.err(26546):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1893)
01-11 16:09:38.466: W/System.err(26546):    at android.app.ActivityThread.access$1500(ActivityThread.java:135)
01-11 16:09:38.466: W/System.err(26546):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1054)
01-11 16:09:38.466: W/System.err(26546):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-11 16:09:38.466: W/System.err(26546):    at android.os.Looper.loop(Looper.java:150)
01-11 16:09:38.476: W/System.err(26546):    at android.app.ActivityThread.main(ActivityThread.java:4385)
01-11 16:09:38.476: W/System.err(26546):    at java.lang.reflect.Method.invokeNative(Native Method)
01-11 16:09:38.476: W/System.err(26546):    at java.lang.reflect.Method.invoke(Method.java:507)
01-11 16:09:38.476: W/System.err(26546):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
01-11 16:09:38.476: W/System.err(26546):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
01-11 16:09:38.476: W/System.err(26546):    at dalvik.system.NativeStart.main(Native Method)
How to solve:

Use SurfaceHolder.Callback -> surfaceCreated to know when you can start the AutoFocus. If the surfaceholder isn’t created (lasted some time) autofocus will fail.

###

You might want to make sure that the phone supports autofocus. It is quite easy to check this:

Camera.Parameters p = mCamera.getParameters();
List<String> focusModes = p.getSupportedFocusModes();

if(focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
    //Phone supports autofocus!
}
else {
    //Phone does not support autofocus!
}

###

I propose two solutions that worked for me. 1) Stop and Resume the camera correctly. I do it by calling these methods on onPause and onResume, also in the middle of the camera Preview, where I scan QR codes in my app:

public void stopCamera(){
     mCamera.cancelAutoFocus();
     mCamera.setPreviewCallback(null);
     mCamera.stopPreview();  
     mPreviewing = false;
     }

public void rethrottleCamera(){
        updateViews(); //Updates my Layouts
        mPreviewing = true;
        mCamera.startPreview();
        mCamera.setPreviewCallback(previewCb);  
        mCamera.autoFocus(autoFocusCB); 
        }   

2)Very tricky but worked like magic! Make sure that you call autofocus AFTER the preview surface has been created. To do this run Autofocus with a 200ms delay, to buy time for the surface to be created. Set this by pressing ctrl+clic over a “CameraPreview” object declaration, such as:

CameraPreview my_camera;

Look for the “public void surfaceChanged” method and make this changes:

//Add a delay to AUTOFOCUS after mCamera.startpreview();!!:
    mCamera.startPreview();                 
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {                    
            mCamera.autoFocus(autoFocusCallback);
            }
    }, 200); //<-200 millisecond delay

    //If you call autofocus right after startPreview, chances are,
    //that the previewSurface will have not been created yet,
    //and autofocus will fail:
    mCamera.startPreview();               //Bad idea!
    mCamera.autoFocus(autoFocusCallback); //Bad idea!

There are plenty other fixes, but these two may save your day.

###

i have found a nice solution
So lets catch exception this simply, and try again to call autofocus on some devices (i.e. sony experia and some others)
What is for about time of delay between retries (1 second)
i don’t love any “magic” numbers in code, so this’s may be too large or too small in some cases. Its enough for me)

public void requestAutoFocus(Handler handler, int message) {
    if(camera != null && previewing) {
        autoFocusCallback.setHandler(handler, message);
        scheduleAutoFocus();
    }
}

public void safeAutoFocus() {
    try {
        camera.autoFocus(autoFocusCallback);
    } catch (RuntimeException e) {
        // Horrible hack to deal with autofocus errors on Sony devices
        // See https://github.com/dm77/barcodescanner/issues/7 for example
        scheduleAutoFocus(); // wait 1 sec and then do check again
    }
}

private void scheduleAutoFocus() {
    mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
}

private Runnable doAutoFocus = new Runnable() {
    public void run() {
        if(camera != null && previewing) {
            safeAutoFocus();
        }
    }
};

and here is start and stop methods

public void startPreview() {
    if (camera != null && !previewing) {
        camera.startPreview();
        camera.autoFocus(autoFocusCallback);
        previewing = true;
    }
}

public void stopPreview() {
    if(camera != null && previewing) {
        try {
            camera.cancelAutoFocus();
            if(!useOneShotPreviewCallback) {
                camera.setPreviewCallback(null);
            }
            camera.stopPreview();
            previewCallback.setHandler(null, 0);
            autoFocusCallback.setHandler(null, 0);
            previewing = false;
        } catch(Exception e) {
            Log.e(TAG, e.toString(), e);
        }
    }
}

reference: https://github.com/dm77/barcodescanner/blob/master/core/src/main/java/me/dm7/barcodescanner/core/CameraPreview.java

###

Make sure you’re calling the autoFocus function after calling the start preview.
According to the android documentation

This method is only valid when preview is active (between
startPreview() and before stopPreview()).

If you’re still facing any error try Rasmus’s and zwebie’s solution in the same order.

###

There are many solutions, but this is an easy, dead cheap option that worked for me:

try{
   mCamera.autoFocus(autoFocusCB); //Or whatever part of code that crashes
   }
catch(Exception e){
   Log.v("joshtag","THIS PHONE DOES NOT SUPPORT AUTOFOCUS!!"); //a warning, popup, whatever
   }

VoilĂ ! Trap deactivated.

Leave a Reply

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