Capture picture without preview using camera2 API

What I want to achieve is capturing a picture without showing the preview, sending directly the output to an ImageReader.
I have used the Camera2Basic example as a starting point.
However, the callback of my ImageReader is never called, hence no image is sent to its Surface.
Do I really need to display a preview first?

This is the camera code, which is ordered following the flow of the asynchronous callbacks:

  • any way to discover Android devices on your network?
  • View.setFocusable() and View.setClickable() have contrary effect in custom ArrayAdapter
  • android show notification with a popup on top of any application
  • Receiving package install and uninstall events
  • Enable/disable data connection in android programmatically
  • What's the point of FILL_AND_STROKE?
  • private ImageReader imageReader;
    private Handler backgroundHandler;
    private HandlerThread backgroundThread;
    private String cameraId;
    private CameraDevice cameraDevice;
    private CameraCaptureSession cameraCaptureSession;
        @Override
        public void onCreate() {
            setupCamera2();
        }
    
        private void setupCamera2() {
            CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    
            try {
    
                for (String cameraId : manager.getCameraIdList()) {
                CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
    
                if (characteristics.get(CameraCharacteristics.LENS_FACING) != CameraCharacteristics.LENS_FACING_FRONT) {
                    continue;
                }
    
                this.cameraId = cameraId;
    
                int[] picSize = Settings.getPictureSize();
                int picWidth = picSize[0];
                int picHeight = picSize[1];
    
                imageReader = ImageReader.newInstance(picWidth, picHeight, ImageFormat.JPEG, 2);
                imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler);
                }
    
            } catch (CameraAccessException | NullPointerException e) {
                e.printStackTrace();
            }
        }
    
    
        private void openCamera2() {
            CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
            try {
    
                manager.openCamera(cameraId, cameraStateCallback, backgroundHandler);
    
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    
    
    
        private final CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(CameraDevice device) {
                cameraDevice = device;
                createCameraCaptureSession();
            }
    
            @Override
            public void onDisconnected(CameraDevice cameraDevice) {}
    
            @Override
            public void onError(CameraDevice cameraDevice, int error) {}
        };
    
    
    
        private void createCaptureSession() {
            List<Surface> outputSurfaces = new LinkedList<>();
            outputSurfaces.add(imageReader.getSurface());
    
            try {
    
                cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(CameraCaptureSession session) {
                        cameraCaptureSession = session;
                    }
    
                    @Override
                    public void onConfigureFailed(CameraCaptureSession session) {}
                }, null);
    
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    
    
        private final ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                createCaptureRequest();
            }
        };
    
    
        private void createCaptureRequest() {
            try {
    
                CaptureRequest.Builder requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
                requestBuilder.addTarget(imageReader.getSurface());
    
                // Focus
                requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
    
                // Orientation
                int rotation = windowManager.getDefaultDisplay().getRotation();
                requestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
    
                cameraCaptureSession.capture(requestBuilder.build(), camera2Callback, null);
    
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    

    Related posts:

    adb connection over tcp not working now
    Bluetooth SPP between Android and other device, UUID and PIN questions
    Obtain the Linux UID of an Android App
    Android: HorizontalScrollView smoothScroll animation time
    Android 4.2.2 adb can&#039;t find devices
    ClassCastException: RestTemplate returning List&lt;LinkedHashMap&gt; instead of List&lt;...
  • AudioFlinger could not create track. status: -12
  • Returning a blob with json
  • Build release apk with customize name format in Android Studio
  • GoogleApiClient.connect()' was expected to be of type interface but was found to be virtual
  • ViewPager with Fragments inside PopupWindow (or DialogFragment) - Error no view found for id for fragment
  • getting Dagger to inject mock objects when doing espresso functional testing for Android
  • 3 Solutions collect form web for “Capture picture without preview using camera2 API”

    You should capture photos in “onConfigured” function but not onImageAvailable.

    public void onConfigured(CameraCaptureSession session) {
                cameraCaptureSession = session;
                createCaptureRequest();
            }
    

    In this function “onImageAvailable”,you should save images,

    Image image = mImageReader.acquireLatestImage();
    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    byte[] bytes = new byte[buffer.remaining()];
    buffer.get(bytes);
    try {
        save(bytes, file);
    } catch (IOException e) {
        e.printStackTrace();
    }
    image.close();
    

    “onImageAvailable” function will be invoked after session.capture() .

    Since I struggled a lot finding out how this works, here is a minimal working Android Service which can process Image data. It probably needs some time after create before you can call start the service, though!

    import android.app.Service;
    import android.content.Intent;
    import android.graphics.ImageFormat;
    import android.hardware.camera2.CameraAccessException;
    import android.hardware.camera2.CameraCaptureSession;
    import android.hardware.camera2.CameraCharacteristics;
    import android.hardware.camera2.CameraDevice;
    import android.hardware.camera2.CameraManager;
    import android.hardware.camera2.CaptureRequest;
    import android.media.Image;
    import android.media.ImageReader;
    import android.os.IBinder;
    import android.util.Log;
    
    import java.util.Arrays;
    
    public class VideoProcessingService extends Service {
        private static final String TAG = "VideoProcessing";
        private static final int CAMERA = CameraCharacteristics.LENS_FACING_FRONT;
        private CameraDevice camera;
        private CameraCaptureSession session;
        private ImageReader imageReader;
    
        private CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(CameraDevice camera) {
                VideoProcessingService.this.camera = camera;
            }
    
            @Override
            public void onDisconnected(CameraDevice camera) {}
    
            @Override
            public void onError(CameraDevice camera, int error) {}
        };
    
        private CameraCaptureSession.StateCallback sessionStateCallback = new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(CameraCaptureSession session) {
                VideoProcessingService.this.session = session;
                try {
                    session.setRepeatingRequest(createCaptureRequest(), null, null);
                } catch (CameraAccessException e){
                    Log.e(TAG, e.getMessage());
                }
            }
    
            @Override
            public void onConfigureFailed(CameraCaptureSession session) {}
        };
    
        private ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader){
                Image img = reader.acquireLatestImage();
                processImage(img);
                img.close();
            }
        };
    
        @Override
        public void onCreate() {
            CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
            try {
                manager.openCamera(getCamera(manager), cameraStateCallback, null);
                imageReader = ImageReader.newInstance(320, 240, ImageFormat.YUV_420_888, 30 * 600); //fps * 10 min
                imageReader.setOnImageAvailableListener(onImageAvailableListener, null);
            } catch (CameraAccessException e){
                Log.e(TAG, e.getMessage());
            }
        }
    
        /**
         *  Return the Camera Id which matches the field CAMERA.
         */
        public String getCamera(CameraManager manager){
            try {
                for (String cameraId : manager.getCameraIdList()) {
                    CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
                    int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
                    if (cOrientation == CAMERA) {
                        return cameraId;
                    }
                }
            } catch (CameraAccessException e){
                e.printStackTrace();
            }
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            try {
                camera.createCaptureSession(Arrays.asList(imageReader.getSurface()), sessionStateCallback, null);
            } catch (CameraAccessException e){
                Log.e(TAG, e.getMessage());
            }
            return super.onStartCommand(intent, flags, startId);
        }
    
        @Override
        public void onDestroy() {
            try {
                session.abortCaptures();
            } catch (CameraAccessException e){
                Log.e(TAG, e.getMessage());
            }
            session.close();
        }
    
        /**
         *  Process image data as desired.
         */
        private void processImage(Image image){
            //Process image data
        }
    
        private CaptureRequest createCaptureRequest() {
            try {
                CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
                builder.addTarget(imageReader.getSurface());
                return builder.build();
            } catch (CameraAccessException e) {
                Log.e(TAG, e.getMessage());
                return null;
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
    

    Since I’ve been struggling with CAMERA2 API for a long time, looking for how to take pictures without preview from all available cameras on the device, I’ve created a project on GitHub that does exactly what you want (and maybe more)
    https://github.com/hzitoun/android-camera2-secret-picture-taker

    enter image description here

    Hope that helped 🙂

    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.