title: Android Camera2, take picture continuously
body: <p>I need to take pictures continuously with Camera2 API. It works fine on high end devices (for instance a Nexus 5X), but on slower ones (for instance a Samsung Galaxy A3), the preview freezes.</p>
  
  <p>The code is a bit long, so I post only the most relevant parts:</p>
  
  <p>Method called to start my preview:</p>
  
  <pre><code>private void startPreview() {
  
      SurfaceTexture texture = mTextureView.getSurfaceTexture();
  
      if(texture != null) {
  
          try {
  
              // We configure the size of default buffer to be the size of camera preview we want.
              texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
  
              // This is the output Surface we need to start preview.
              Surface surface = new Surface(texture);
  
              // We set up a CaptureRequest.Builder with the output Surface.
              mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
              mPreviewRequestBuilder.addTarget(surface);
  
              // Here, we create a CameraCaptureSession for camera preview.
              mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
  
                      @Override
                      public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
  
                          // If the camera is already closed, return:
                          if (mCameraDevice == null) { return; }
  
                          // When the session is ready, we start displaying the preview.
                          mCaptureSession = cameraCaptureSession;
  
                          // Auto focus should be continuous for camera preview.
                          mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                          mPreviewRequest = mPreviewRequestBuilder.build();
  
                          // Start the preview
                          try { mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mPreviewBackgroundHandler); }
                          catch (CameraAccessException e) { e.printStackTrace(); }
                      }
  
                      @Override
                      public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                          Log.e(TAG, "Configure failed");
                      }
                  }, null
              );
          }
          catch (CameraAccessException e) { e.printStackTrace(); }
      }
  }
  </code></pre>
  
  <p>Method called to take a picture:</p>
  
  <pre><code>private void takePicture() {
  
      try {
  
          CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
          captureBuilder.addTarget(mImageReader.getSurface());
          mCaptureSession.capture(captureBuilder.build(), null, mCaptureBackgroundHandler);
      }
      catch (CameraAccessException e) { e.printStackTrace(); }
  }
  </code></pre>
  
  <p>And here is my ImageReader:</p>
  
  <pre><code>private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
  
      @Override
      public void onImageAvailable(final ImageReader reader) {
  
          mSaveBackgroundHandler.post(new Runnable() {
  
              @Override
              public void run() {
  
                  // Set the destination file:
                  File destination = new File(getExternalFilesDir(null), "image_" + mNumberOfImages + ".jpg");
                  mNumberOfImages++;
  
                  // Acquire the latest image:
                  Image image = reader.acquireLatestImage();
  
                  // Save the image:
                  ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                  byte[] bytes = new byte[buffer.remaining()];
                  buffer.get(bytes);
  
                  FileOutputStream output = null;
                  try {
                      output = new FileOutputStream(destination);
                      output.write(bytes);
                  }
                  catch (IOException e) { e.printStackTrace(); }
                  finally {
  
                      image.close();
  
                      if (null != output) {
  
                          try { output.close(); }
                          catch (IOException e) { e.printStackTrace(); }
                      }
                  }
  
                  // Take a new picture if needed:
                  if(mIsTakingPictures) {
                      takePicture();
                  }
              }
          });
      }
  };
  </code></pre>
  
  <p>I have a button that toggle the mIsTakingPictures boolean, and makes the first takePicture call.</p>
  
  <p>To recap, I'm using 3 threads:</p>
  
  <ul>
  <li>one for the preview</li>
  <li>one for the capture</li>
  <li>one for the image saving</li>
  </ul>
  
  <p>What can be the cause of this freeze?</p>