From 5d10277d7be0879b4a9f3a3e147ac8d009f9480f Mon Sep 17 00:00:00 2001 From: Michael <15450970+michaelspecht@users.noreply.github.com> Date: Fri, 8 Jan 2021 17:17:52 -0500 Subject: [PATCH] add try catch to catch exceptions when takePicture fails (#1024) * add try catch to catch exceptions when takePicture fails, to give the user a better experience than an app crash * do not log errors, as they are alreayd logged by the camera engine, and do not put try catch around DNG captures Co-authored-by: Mattia Iavarone --- .../otaliastudios/cameraview/CameraUtils.java | 2 +- .../picture/Full1PictureRecorder.java | 99 ++++++++++--------- .../picture/Full2PictureRecorder.java | 9 +- 3 files changed, 62 insertions(+), 48 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraUtils.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraUtils.java index bbfdf5fb..19e409a4 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraUtils.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraUtils.java @@ -158,7 +158,7 @@ public class CameraUtils { @NonNull final BitmapCallback callback) { decodeBitmap(source, Integer.MAX_VALUE, Integer.MAX_VALUE, callback); } - + /** * Decodes an input byte array and outputs a Bitmap that is ready to be displayed. * The difference with {@link android.graphics.BitmapFactory#decodeByteArray(byte[], int, int)} diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full1PictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full1PictureRecorder.java index 0d099e78..45b6edbe 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full1PictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full1PictureRecorder.java @@ -1,10 +1,12 @@ package com.otaliastudios.cameraview.picture; import android.hardware.Camera; +import android.util.Log; import androidx.annotation.NonNull; import androidx.exifinterface.media.ExifInterface; +import com.otaliastudios.cameraview.CameraException; import com.otaliastudios.cameraview.PictureResult; import com.otaliastudios.cameraview.engine.Camera1Engine; import com.otaliastudios.cameraview.engine.offset.Reference; @@ -44,57 +46,62 @@ public class Full1PictureRecorder extends FullPictureRecorder { // or takePicture can hang and leave the camera in a bad state. mCamera.setPreviewCallbackWithBuffer(null); mEngine.getFrameManager().release(); - mCamera.takePicture( - new Camera.ShutterCallback() { - @Override - public void onShutter() { - LOG.i("take(): got onShutter callback."); - dispatchOnShutter(true); - } - }, - null, - null, - new Camera.PictureCallback() { - @Override - public void onPictureTaken(byte[] data, final Camera camera) { - LOG.i("take(): got picture callback."); - int exifRotation; - try { - ExifInterface exif = new ExifInterface(new ByteArrayInputStream(data)); - int exifOrientation = exif.getAttributeInt( - ExifInterface.TAG_ORIENTATION, - ExifInterface.ORIENTATION_NORMAL); - exifRotation = ExifHelper.getOrientation(exifOrientation); - } catch (IOException e) { - exifRotation = 0; + try { + mCamera.takePicture( + new Camera.ShutterCallback() { + @Override + public void onShutter() { + LOG.i("take(): got onShutter callback."); + dispatchOnShutter(true); } - mResult.data = data; - mResult.rotation = exifRotation; - LOG.i("take(): starting preview again. ", Thread.currentThread()); + }, + null, + null, + new Camera.PictureCallback() { + @Override + public void onPictureTaken(byte[] data, final Camera camera) { + LOG.i("take(): got picture callback."); + int exifRotation; + try { + ExifInterface exif = new ExifInterface(new ByteArrayInputStream(data)); + int exifOrientation = exif.getAttributeInt( + ExifInterface.TAG_ORIENTATION, + ExifInterface.ORIENTATION_NORMAL); + exifRotation = ExifHelper.getOrientation(exifOrientation); + } catch (IOException e) { + exifRotation = 0; + } + mResult.data = data; + mResult.rotation = exifRotation; + LOG.i("take(): starting preview again. ", Thread.currentThread()); - // It's possible that by the time this callback is invoked, we're not previewing - // anymore, so check before restarting preview. - if (mEngine.getState().isAtLeast(CameraState.PREVIEW)) { - camera.setPreviewCallbackWithBuffer(mEngine); - Size previewStreamSize = mEngine.getPreviewStreamSize(Reference.SENSOR); - if (previewStreamSize == null) { - throw new IllegalStateException("Preview stream size " + - "should never be null here."); + // It's possible that by the time this callback is invoked, we're not previewing + // anymore, so check before restarting preview. + if (mEngine.getState().isAtLeast(CameraState.PREVIEW)) { + camera.setPreviewCallbackWithBuffer(mEngine); + Size previewStreamSize = mEngine.getPreviewStreamSize(Reference.SENSOR); + if (previewStreamSize == null) { + throw new IllegalStateException("Preview stream size " + + "should never be null here."); + } + // Need to re-setup the frame manager, otherwise no frames are processed + // after takePicture() is called + mEngine.getFrameManager().setUp( + mEngine.getFrameProcessingFormat(), + previewStreamSize, + mEngine.getAngles() + ); + camera.startPreview(); } - // Need to re-setup the frame manager, otherwise no frames are processed - // after takePicture() is called - mEngine.getFrameManager().setUp( - mEngine.getFrameProcessingFormat(), - previewStreamSize, - mEngine.getAngles() - ); - camera.startPreview(); + dispatchResult(); } - dispatchResult(); } - } - ); - LOG.i("take() returned."); + ); + LOG.i("take() returned."); + } catch (Exception e) { + mError = e; + dispatchResult(); + } } @Override diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java index 10ea5775..1c95543b 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java @@ -8,6 +8,7 @@ import android.hardware.camera2.TotalCaptureResult; import android.media.Image; import android.media.ImageReader; import android.os.Build; +import android.util.Log; import com.otaliastudios.cameraview.PictureResult; import com.otaliastudios.cameraview.controls.PictureFormat; @@ -86,7 +87,13 @@ public class Full2PictureRecorder extends FullPictureRecorder public void onCaptureCompleted(@NonNull ActionHolder holder, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) { - super.onCaptureCompleted(holder, request, result); + try { + super.onCaptureCompleted(holder, request, result); + } catch (Exception e) { + mError = e; + dispatchResult(); + } + if (mResult.format == PictureFormat.DNG) { mDngCreator = new DngCreator(holder.getCharacteristics(this), result); mDngCreator.setOrientation(ExifHelper.getExifOrientation(mResult.rotation));