diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index aee3774087ba..7391f3090565 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.0-nullsafety.1 + +* Added a timeout to the pre-capture sequence on Android to prevent crashes when the camera cannot get a focus. + ## 0.8.0-nullsafety * Migrated to null safety. diff --git a/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index a5f8647afb0b..5169a3babb74 100644 --- a/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -36,6 +36,7 @@ import android.os.Build.VERSION_CODES; import android.os.Handler; import android.os.Looper; +import android.os.SystemClock; import android.util.Log; import android.util.Range; import android.util.Rational; @@ -73,6 +74,9 @@ interface ErrorCallback { public class Camera { private static final String TAG = "Camera"; + /** Timeout for the pre-capture sequence. */ + private static final long PRECAPTURE_TIMEOUT_MS = 1000; + private final SurfaceTextureEntry flutterTexture; private final CameraManager cameraManager; private final DeviceOrientationManager deviceOrientationListener; @@ -105,6 +109,7 @@ public class Camera { private boolean useAutoFocus = true; private Range fpsRange; private PlatformChannel.DeviceOrientation lockedCaptureOrientation; + private long preCaptureStartTime; private static final HashMap supportedImageFormats; // Current supported outputs @@ -503,11 +508,16 @@ private void processCapture(CaptureResult result) { || aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED || aeState == CaptureRequest.CONTROL_AE_STATE_CONVERGED) { pictureCaptureRequest.setState(State.waitingPreCaptureReady); + setPreCaptureStartTime(); } break; case waitingPreCaptureReady: if (aeState == null || aeState != CaptureRequest.CONTROL_AE_STATE_PRECAPTURE) { runPictureCapture(); + } else { + if (hitPreCaptureTimeout()) { + unlockAutoFocus(); + } } } } @@ -1142,6 +1152,20 @@ public void stopImageStream() throws CameraAccessException { startPreview(); } + /** Sets the time the pre-capture sequence started. */ + private void setPreCaptureStartTime() { + preCaptureStartTime = SystemClock.elapsedRealtime(); + } + + /** + * Check if the timeout for the pre-capture sequence has been reached. + * + * @return true if the timeout is reached; otherwise false is returned. + */ + private boolean hitPreCaptureTimeout() { + return (SystemClock.elapsedRealtime() - preCaptureStartTime) > PRECAPTURE_TIMEOUT_MS; + } + private void closeCaptureSession() { if (cameraCaptureSession != null) { cameraCaptureSession.close(); diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 7ed08d892de8..5b98c39acd99 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -2,7 +2,7 @@ name: camera description: A Flutter plugin for getting information about and controlling the camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video, and streaming image buffers to dart. -version: 0.8.0-nullsafety +version: 0.8.0-nullsafety.1 homepage: https://github.com/flutter/plugins/tree/master/packages/camera/camera dependencies: diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index b37b7701a14f..40ce29e363b1 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -1268,7 +1268,7 @@ class MockCameraPlatform extends Mock Future createCamera( CameraDescription description, ResolutionPreset? resolutionPreset, { - bool enableAudio = true, + bool enableAudio = false, }) => mockPlatformException ? throw PlatformException(code: 'foo', message: 'bar')