From 3deb404463c0f77fe040334890b5913f551464b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Adri=C3=A1n?= Date: Tue, 13 Jun 2023 11:04:28 -0300 Subject: [PATCH 1/6] try/catch getCameraInfo() on Camera1Engine.java Fix Runtime Exception on devices trying to use Camera1 Fatal Exception: java.lang.RuntimeException: Fail to get camera info at android.hardware.Camera.getCameraInfo(Camera.java:332) at com.otaliastudios.cameraview.engine.Camera1Engine.collectCameraInfo(Camera1Engine.java:144) --- .../com/otaliastudios/cameraview/engine/Camera1Engine.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java index c694b0fc..70d911ad 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -141,7 +141,11 @@ protected boolean collectCameraInfo(@NonNull Facing facing) { "Cameras:", Camera.getNumberOfCameras()); Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) { - Camera.getCameraInfo(i, cameraInfo); + try { + Camera.getCameraInfo(i, cameraInfo); + } catch (RuntimeException e) { + return false; + } if (cameraInfo.facing == internalFacing) { getAngles().setSensorOffset(facing, cameraInfo.orientation); mCameraId = i; From a4b9ecb6e2dbab993c78563c58c045d44f49c1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Adri=C3=A1n?= Date: Sun, 7 Jan 2024 12:10:53 -0300 Subject: [PATCH 2/6] Fix Runtime Exception on devices trying to use Camera1 Fatal Exception: java.lang.RuntimeException: Fail to get camera info at android.hardware.Camera.getCameraInfo(Camera.java:332) at com.otaliastudios.cameraview.engine.Camera1Engine.collectCameraInfo(Camera1Engine.java:144) --- .../java/com/otaliastudios/cameraview/engine/Camera1Engine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java index 70d911ad..45b6e146 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -144,7 +144,7 @@ protected boolean collectCameraInfo(@NonNull Facing facing) { try { Camera.getCameraInfo(i, cameraInfo); } catch (RuntimeException e) { - return false; + continue; } if (cameraInfo.facing == internalFacing) { getAngles().setSensorOffset(facing, cameraInfo.orientation); From 3db652d4d298de18bd971de7f78d4f41c3ef72fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Adri=C3=A1n?= Date: Sun, 7 Jan 2024 12:40:37 -0300 Subject: [PATCH 3/6] Fix mutiple getParameters() unhandled RuntimeException Every time getParameters() is called, it can fail with RuntimeException: "getParameters failed (empty parameters)" So the fix is to try/catch and Log.e the failure. Please tell me if you need to throw REASON_UNLNOWN exception or let the app continue. LOGCAT CRASH: Exception java.lang.RuntimeException: getParameters failed (empty parameters) at android.hardware.Camera.native_getParameters at android.hardware.Camera.getParameters (Camera.java:3088) at com.otaliastudios.cameraview.engine.Camera1Engine$3.run (Camera1Engine.java:579) at com.otaliastudios.cameraview.engine.orchestrator.CameraStateOrchestrator$3.run (CameraStateOrchestrator.java:100) at com.otaliastudios.cameraview.engine.orchestrator.CameraOrchestrator$1.call (CameraOrchestrator.java:84) at com.otaliastudios.cameraview.engine.orchestrator.CameraOrchestrator$1.call (CameraOrchestrator.java:81) at com.otaliastudios.cameraview.engine.orchestrator.CameraOrchestrator$3.run (CameraOrchestrator.java:152) at com.otaliastudios.cameraview.internal.WorkerHandler.run (WorkerHandler.java:137) at com.otaliastudios.cameraview.engine.orchestrator.CameraOrchestrator.execute (CameraOrchestrator.java:147) at com.otaliastudios.cameraview.engine.orchestrator.CameraOrchestrator.access$100 (CameraOrchestrator.java:34) at com.otaliastudios.cameraview.engine.orchestrator.CameraOrchestrator$2.run (CameraOrchestrator.java:137) at android.os.Handler.handleCallback (Handler.java:836) at android.os.Handler.dispatchMessage (Handler.java:103) at android.os.Looper.loop (Looper.java:203) at android.os.HandlerThread.run (HandlerThread.java:61) --- .../cameraview/engine/Camera1Engine.java | 92 ++++++++++++++----- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java index 45b6e146..7d153b62 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -528,8 +528,14 @@ public void setFlash(@NonNull Flash flash) { new Runnable() { @Override public void run() { - Camera.Parameters params = mCamera.getParameters(); - if (applyFlash(params, old)) mCamera.setParameters(params); + try { + Camera.Parameters params = mCamera.getParameters(); + if (applyFlash(params, old)) mCamera.setParameters(params); + } catch (RuntimeException e) { + LOG.e("onSetFlash:", "Failed to get params from camera. Maybe low level problem with camera or camera has already released?"); + //Should throw exception? Looks inappropriate at this point if camera is working... + //throw new CameraException(e, CameraException.REASON_FAILED_TO_START_PREVIEW); + } } }); } @@ -552,8 +558,14 @@ public void setLocation(@Nullable Location location) { new Runnable() { @Override public void run() { - Camera.Parameters params = mCamera.getParameters(); - if (applyLocation(params, oldLocation)) mCamera.setParameters(params); + try { + Camera.Parameters params = mCamera.getParameters(); + if (applyLocation(params, oldLocation)) mCamera.setParameters(params); + } catch (RuntimeException e) { + LOG.e("onSetLocation:", "Failed to get params from camera. Maybe low level problem with camera or camera has already released?"); + //Should throw exception? Looks inappropriate at this point if camera is working... + //throw new CameraException(e, CameraException.REASON_FAILED_TO_START_PREVIEW); + } } }); } @@ -580,8 +592,14 @@ public void setWhiteBalance(@NonNull WhiteBalance whiteBalance) { new Runnable() { @Override public void run() { - Camera.Parameters params = mCamera.getParameters(); - if (applyWhiteBalance(params, old)) mCamera.setParameters(params); + try { + Camera.Parameters params = mCamera.getParameters(); + if (applyWhiteBalance(params, old)) mCamera.setParameters(params); + } catch (RuntimeException e) { + LOG.e("onSetWhiteBalance:", "Failed to get params from camera. Maybe low level problem with camera or camera has already released?"); + //Should throw exception? Looks inappropriate at this point if camera is working... + //throw new CameraException(e, CameraException.REASON_FAILED_TO_START_PREVIEW); + } } }); } @@ -609,8 +627,14 @@ public void setHdr(@NonNull Hdr hdr) { new Runnable() { @Override public void run() { - Camera.Parameters params = mCamera.getParameters(); - if (applyHdr(params, old)) mCamera.setParameters(params); + try { + Camera.Parameters params = mCamera.getParameters(); + if (applyHdr(params, old)) mCamera.setParameters(params); + } catch (RuntimeException e) { + LOG.e("onSetHdr:", "Failed to get params from camera. Maybe low level problem with camera or camera has already released?"); + //Should throw exception? Looks inappropriate at this point if camera is working... + //throw new CameraException(e, CameraException.REASON_FAILED_TO_START_PREVIEW); + } } }); } @@ -635,12 +659,18 @@ public void setZoom(final float zoom, @Nullable final PointF[] points, final boo new Runnable() { @Override public void run() { - Camera.Parameters params = mCamera.getParameters(); - if (applyZoom(params, old)) { - mCamera.setParameters(params); - if (notify) { - getCallback().dispatchOnZoomChanged(mZoomValue, points); + try { + Camera.Parameters params = mCamera.getParameters(); + if (applyZoom(params, old)) { + mCamera.setParameters(params); + if (notify) { + getCallback().dispatchOnZoomChanged(mZoomValue, points); + } } + } catch (RuntimeException e) { + LOG.e("onSetZoom:", "Failed to get params from camera. Maybe low level problem with camera or camera has already released?"); + //Should throw exception? Looks inappropriate at this point if camera is working... + //throw new CameraException(e, CameraException.REASON_FAILED_TO_START_PREVIEW); } } }); @@ -670,13 +700,19 @@ public void setExposureCorrection(final float EVvalue, @NonNull final float[] bo new Runnable() { @Override public void run() { - Camera.Parameters params = mCamera.getParameters(); - if (applyExposureCorrection(params, old)) { - mCamera.setParameters(params); - if (notify) { - getCallback().dispatchOnExposureCorrectionChanged(mExposureCorrectionValue, - bounds, points); + try { + Camera.Parameters params = mCamera.getParameters(); + if (applyExposureCorrection(params, old)) { + mCamera.setParameters(params); + if (notify) { + getCallback().dispatchOnExposureCorrectionChanged(mExposureCorrectionValue, + bounds, points); + } } + } catch (RuntimeException e) { + LOG.e("onSetExposureCorrection:", "Failed to get params from camera. Maybe low level problem with camera or camera has already released?"); + //Should throw exception? Looks inappropriate at this point if camera is working... + //throw new CameraException(e, CameraException.REASON_FAILED_TO_START_PREVIEW); } } }); @@ -748,8 +784,14 @@ public void setPreviewFrameRate(float previewFrameRate) { new Runnable() { @Override public void run() { - Camera.Parameters params = mCamera.getParameters(); - if (applyPreviewFrameRate(params, old)) mCamera.setParameters(params); + try { + Camera.Parameters params = mCamera.getParameters(); + if (applyPreviewFrameRate(params, old)) mCamera.setParameters(params); + } catch (RuntimeException e) { + LOG.e("onSetPreviewFrameRate:", "Failed to get params from camera. Maybe low level problem with camera or camera has already released?"); + //Should throw exception? Looks inappropriate at this point if camera is working... + //throw new CameraException(e, CameraException.REASON_FAILED_TO_START_PREVIEW); + } } }); } @@ -879,7 +921,13 @@ public void run() { getPreview().getSurfaceSize()); MeteringRegions transformed = regions.transform(transform); - Camera.Parameters params = mCamera.getParameters(); + Camera.Parameters params; + try { + params = mCamera.getParameters(); + } catch (RuntimeException re) { + LOG.e("startAutoFocus:", "Failed to get camera parameters"); + throw new CameraException(re, CameraException.REASON_UNKNOWN); + } int maxAF = params.getMaxNumFocusAreas(); int maxAE = params.getMaxNumMeteringAreas(); if (maxAF > 0) params.setFocusAreas(transformed.get(maxAF, transform)); From 84a32b8fe02dfd2744781358287a84c5c7bcde22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Adri=C3=A1n?= Date: Thu, 11 Jan 2024 13:50:00 -0300 Subject: [PATCH 4/6] Catch CodecException --- .../cameraview/video/encoding/VideoMediaEncoder.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/VideoMediaEncoder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/VideoMediaEncoder.java index 770c3ad7..4a818a35 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/VideoMediaEncoder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/VideoMediaEncoder.java @@ -81,7 +81,11 @@ protected void onPrepare(@NonNull MediaEncoderEngine.Controller controller, long } mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mSurface = mMediaCodec.createInputSurface(); - mMediaCodec.start(); + try { + mMediaCodec.start(); + } catch (MediaCodec.CodecException e) { + throw new RuntimeException(e); + } } @EncoderThread From c1ab8c8543560d7040a314b49e01cfcb1a8c95ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Adri=C3=A1n?= Date: Thu, 8 Feb 2024 18:34:23 -0300 Subject: [PATCH 5/6] Update CameraListener.java --- .../otaliastudios/cameraview/CameraListener.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraListener.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraListener.java index 34161eea..2fd07798 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraListener.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraListener.java @@ -169,5 +169,21 @@ public void onVideoRecordingEnd() { public void onPictureShutter() { } + + /** + * Notifies that a finger gesture just triggered a swipe left event. + * This can be used to exchange between different filters or to + * swap between front and back cameras. + */ + @UiThread + public void onSwipeLeft() {} + + /** + * Notifies that a finger gesture just triggered a swipe right event. + * This can be used to exchange between different filters or to + * swap between front and back cameras. + */ + @UiThread + public void onSwipeRight() {} } From 0470e358b79b61bbeace6a6b46b6cc38b119512e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Adri=C3=A1n?= Date: Thu, 8 Feb 2024 18:42:10 -0300 Subject: [PATCH 6/6] Update CameraView.java --- .../otaliastudios/cameraview/CameraView.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index f5140eb2..a99702ce 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -154,6 +154,9 @@ public class CameraView extends FrameLayout implements LifecycleObserver { @VisibleForTesting TapGestureFinder mTapGestureFinder; @VisibleForTesting ScrollGestureFinder mScrollGestureFinder; + private float x1,x2; + static final int MIN_SWIPE_DISTANCE = 150; + // Views @VisibleForTesting GridLinesLayout mGridLinesLayout; @VisibleForTesting MarkerLayout mMarkerLayout; @@ -666,6 +669,32 @@ public boolean onTouchEvent(MotionEvent event) { onGesture(mTapGestureFinder, options); } + if(event.getAction() == MotionEvent.ACTION_DOWN) x1 = event.getX(); + if(event.getAction() == MotionEvent.ACTION_UP) { + x2 = event.getX(); + float deltaX = x2 - x1; + if(deltaX > MIN_SWIPE_DISTANCE) { + mUiHandler.post(new Runnable() { + @Override + public void run() { + for (CameraListener listener : mListeners) { + listener.onSwipeRight(); + } + } + }); + } + if (deltaX < MIN_SWIPE_DISTANCE) { + mUiHandler.post(new Runnable() { + @Override + public void run() { + for (CameraListener listener : mListeners) { + listener.onSwipeLeft(); + } + } + }); + } + } + return true; }