[camera] Added timeout to Android pre-capture sequence (#3558)
* Added timeout for waiting pre-capture state Android
* Fix analysis warning and bumped version
diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md
index aee3774..7391f30 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 a5f8647..5169a3b 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 @@
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 @@
private boolean useAutoFocus = true;
private Range<Integer> fpsRange;
private PlatformChannel.DeviceOrientation lockedCaptureOrientation;
+ private long preCaptureStartTime;
private static final HashMap<String, Integer> supportedImageFormats;
// Current supported outputs
@@ -503,11 +508,16 @@
|| 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 @@
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 7ed08d8..5b98c39 100644
--- a/packages/camera/camera/pubspec.yaml
+++ b/packages/camera/camera/pubspec.yaml
@@ -2,7 +2,7 @@
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 b37b770..40ce29e 100644
--- a/packages/camera/camera/test/camera_test.dart
+++ b/packages/camera/camera/test/camera_test.dart
@@ -1268,7 +1268,7 @@
Future<int> createCamera(
CameraDescription description,
ResolutionPreset? resolutionPreset, {
- bool enableAudio = true,
+ bool enableAudio = false,
}) =>
mockPlatformException
? throw PlatformException(code: 'foo', message: 'bar')