Manual Focus using android camera2 API

12,720

Solution 1

You need to check if the device you're running on actually supports manual controls in camera2.

The key is whether the available capabilities of the camera device lists MANUAL_SENSOR. If so, then you can control the lens by setting the autofocus mode to OFF, and then setting the lens focus distance to your desired value. If MANUAL_SENSOR is not listed, then the device very likely doesn't support manual focus control (Some manufacturers use private interfaces for their default camera app to implement manual focus control, unfortunately).

These should all go into the repeating request you're using to control preview.

Solution 2

Eddy Talvala described everything correctly in his answer, but if you still feel complicated, here is a code snippet that sets focus to infinity (which has value 0f):

CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
int[] capabilities = characteristics
    .get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);

boolean isManualFocusSupported = IntStream.of(capabilities)
    .anyMatch(x -> x == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);

if (isManualFocusSupported) {
    previewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
    previewBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0f);
}
Share:
12,720
Raphaël
Author by

Raphaël

Updated on June 12, 2022

Comments

  • Raphaël
    Raphaël almost 2 years

    I want to develop an Android Camera App for myself (can share it if there are interested people) that has a manual focus while video recording.

    I've added a SeekBar to the google sample Camera2 app but I can't find the way to implement the manual focus.

    I found Manual focus in camera2, android but it doesn't work on my LG G4. The stock camera app is almost perfect since it doesn't allow the manual focus in video mode.

    Does anyone of you have an idea ?

    EDIT: here's the code of the SeekBar listener:

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {}
    
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_OFF);
    }
    
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        float minimumLens = characteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
        float num = (((float)progress) * minimumLens / 100);
        mPreviewBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, num);
    }
    
  • Raphaël
    Raphaël about 7 years
    There is an APK (play.google.com/store/apps/…) to know if a device supports the Camera2 API and LG G4 has a full support and MANUAL_SENSOR is listed. I tried to set autofocus mode to OFF but when I set the lens focus distance to the value of the SeekBar, it doesn't do anything. I edited my main post to add the code I have.
  • Eddy Talvala
    Eddy Talvala about 7 years
    Where do you call mSession.setRepeatingRequest(mPreviewBuilder.build()) after you update the preview builder values?
  • Raphaël
    Raphaël about 7 years
    I actually don't call it but it works when I tried in onProgressChanged(), thank you very much !
  • Eddy Talvala
    Eddy Talvala about 7 years
    Yep - the Builder.set call just updates the one field in your request. You still have to send it to the camera to actually change anything, either via capture() (to capture a single image with those settings) or via setRepeatingRequest (for continual capture).
  • Shanki Bansal
    Shanki Bansal over 5 years
    It's working, Can you please tell me the code for capturing the image with manual focus distance.
  • Fattie
    Fattie about 3 years
    unfortunately this does not work while the camera is actually running :/