5

I am trying to create my own Camera View, I have everything working except the autofocus, I can't seem to figure out why it won't work. Here is my code for CameraView.java

public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder surface_Holder;
    private  Camera main_Camera;
    boolean on;

    public CameraView(Context context, Camera camera){
        super(context);
        main_Camera = camera;
        main_Camera.setDisplayOrientation(90);
        surface_Holder = getHolder();
        surface_Holder.addCallback(this);
        surface_Holder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
    }

    public boolean isOn(){
        return on;
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try{
            main_Camera.setPreviewDisplay(holder);
            main_Camera.startPreview();
        }catch (Exception e){
            Log.d("Error", "Canmera error on surfaceCreated" + e.getMessage());
            main_Camera.release();
            main_Camera = null;
        }

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        if(holder.getSurface()==null){
            return;
        }
        try{
            main_Camera.stopPreview();
        }catch (Exception e){

        }
        try{

            main_Camera.setPreviewDisplay(surface_Holder);
            main_Camera.startPreview();
        }catch (IOException e){
            Log.d("Error", "Camera error on surfaceChanged " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        main_Camera.setPreviewCallback(null);
        main_Camera.stopPreview();
        main_Camera.release();
        main_Camera= null;
    }
}

Inside my manifest I have the following:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
Suji
  • 767
  • 3
  • 12
  • 28

3 Answers3

11

if you added <uses-feature android:name="android.hardware.camera.autofocus" /> to your manifest it doesn't mean the camera will make autofocus. It means you give your app the permission to use camera hardware or software that take care of autofocus.

The purpose of a declaration is to inform any external entity of the set of hardware and software features on which your application depends.

To set your camera to focus you can add this method to your CameraView class:

private void setFocus(String mParameter) {
    Camera.Parameters mParameters = mCamera.getParameters();
    mParameters.setFocusMode(mParameter);
    mCamera.setParameters(mParameters);
}

And then call this method in surfaceChanged() like this:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

    ...//your code here

    // Set focus mode to continuous picture
    setFocus(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);

    // Start camera preview
    mCamera.startPreview();

}

You can choose between these focus parameters:

String FOCUS_MODE_AUTO Auto-focus mode.

String FOCUS_MODE_CONTINUOUS_PICTURE Continuous auto focus mode intended for taking pictures.

String FOCUS_MODE_CONTINUOUS_VIDEO Continuous auto focus mode intended for video recording.

String FOCUS_MODE_EDOF Extended depth of field (EDOF).

String FOCUS_MODE_FIXED Focus is fixed.

String FOCUS_MODE_INFINITY Focus is set at infinity.

String FOCUS_MODE_MACRO Macro (close-up) focus mode.

Chris
  • 6,105
  • 6
  • 38
  • 55
  • Hi Chris, Where should I put the code for forcing autofocus if I do not actually have Java code in my app? I am working with a Unity3D app (C#) that (when deployed to an Android galaxy tablet) scans a serial-number, but the tablet’s camera does not auto-focus. So, your comment that putting that line in the AndroidManifest only allows the use of that feature was informative, because previously I thought that was forcing its use. I only have a bunch of C# scripts in a Unity project. Where should I put such Android-specific code to force camera focus? –  Jun 12 '17 at 07:52
  • 1
    @Joshua sorry, but I have zero knowledges of Unity3D, so I don't think I can help you with that. I think that Unity API is different from the android. Maybe you should open a new question regarding your problem. – Chris Jun 12 '17 at 15:15
  • Thank you @ChrisRock. That helped me. – iSofia Sep 05 '17 at 14:04
  • uses-feature isn't the same as uses-permission. "Google Play uses the elements declared in your app manifest to filter your app from devices that do not meet its hardware and software feature requirements." – Gilles May 17 '18 at 12:14
4
//set camera to continually auto-focus
Camera.Parameters params = c.getParameters();
//*EDIT*//params.setFocusMode("continuous-picture");
//It is better to use defined constraints as opposed to String, thanks to AbdelHady
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
c.setParameters(params);
Javad Jafari
  • 710
  • 6
  • 11
0

Here are some options:

  1. User arsalank2 recommends using "continuous auto focus" as described in this answer. However, it seems that some HTC devices do not support this. Check with: parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTIN‌​UOUS_VIDEO)

  2. You could implement an onSensorChanged listener and focus with a callback when certain criteria are met, see this answer by Juan Acevedo.

  3. Handle each case differently to support the widest range of devices possible. Check what works with different models of different devices as you can't fully rely on what the API level says is implemented.

I would recommend going with option 3 as there seems to be no method that works for every single device.

Community
  • 1
  • 1
halfpastfour.am
  • 5,764
  • 3
  • 44
  • 61