android camera2 api bug fixes

Different types of hardware can stress an application in different ways like the nexus 5x so I took the opportunity to do some android camera2 api bug fixes

Get Code

The code is now on github you can get it from here

https://github.com/mobapptuts/recyclerview_image_gallery.git Tag camera2-write-swap-fix

or else run this command

git clone https://github.com/mobapptuts/recyclerview_image_gallery.git –branch camera2-write-swap-fix

Bug fixes

Create the image file after the camera has gained focus lock

There are a number of places this can be done, I’m going to put the image creation code in the camera capture request callback

CameraCaptureSession.CaptureCallback captureCallback =
                    new CameraCaptureSession.CaptureCallback() {
                        @Override
                        public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
                            super.onCaptureStarted(session, request, timestamp, frameNumber);

                            try {
                                if(mRequestingAppUri != null) {
                                    mImageFile = new File(mRequestingAppUri.getPath());
                                } else {
                                    mImageFile = createImageFile();
                                }


                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }

Add the picture completed state

If we don’t add this state the camera will keep saving images to the same file

private static final int STATE__PICTURE_CAPTURED = 2;

Swap the recyclerview image adapter after the image has been saved

Create a handler for the UI thread which will facilitate communication with the UI thread once the image has been written to  the file.

private final Handler mUiHandler = new Handler(Looper.getMainLooper()) {

     @Override
     public void handleMessage(Message msg) {
         super.handleMessage(msg);

         swapImageAdapter();
     }
 };

Pass the UI handler to the ImageSaver Constructor

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener =
          new ImageReader.OnImageAvailableListener() {
              @Override
              public void onImageAvailable(ImageReader reader) {
                  mBackgroundHandler.post(new ImageSaver(mActivity, reader.acquireNextImage(), mUiHandler));
              }
          };

Call the UI handler once the image has been saved from the ImageSaver runnable

private static class ImageSaver implements Runnable {

       private final Image mImage;
       private final Activity mActivity;
       private final Handler mHandler;

       private ImageSaver(Activity activity, Image image, Handler handler) {
           mActivity = activity;
           mImage = image;
           mHandler = handler;
       }

       @Override
       public void run() {
           ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
           byte[] bytes = new byte[byteBuffer.remaining()];
           byteBuffer.get(bytes);

           FileOutputStream fileOutputStream = null;

           try {
               fileOutputStream = new FileOutputStream(mImageFile);
               fileOutputStream.write(bytes);
           } catch (IOException e) {
               e.printStackTrace();
           } finally {
               mImage.close();
               if(fileOutputStream != null) {
                   try {
                       fileOutputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if(mRequestingAppUri != null) {
                   mRequestingAppUri = null;
                   mActivity.setResult(RESULT_OK);
                   mActivity.finish();
               }
               Message message = mHandler.obtainMessage();
               message.sendToTarget();
           }

       }
   }

Cancel camera capture session repeating requests when the still capture session is ready to be captured

private void captureStillImage() {

 mCameraCaptureSession.stopRepeating();
           mCameraCaptureSession.capture(
                   captureStillBuilder.build(), captureCallback, null
           );

Once the focus is unlocked re-enable the camera capture session repeating request

private void unLockFocus() {
       try {
           mState = STATE_PREVIEW;
           mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                   CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
           mCameraCaptureSession.setRepeatingRequest(mPreviewCaptureRequestBuilder.build(),
                   mSessionCaptureCallback, mBackgroundHandler);
       } catch (CameraAccessException e) {
           e.printStackTrace();
       }
   }
About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>