diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 9af23011ec50..ca77e5e03979 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.6+1 + +* Improve the example to update the controller only if it's initialized successfully. + ## 0.9.6 * Adds audio access permission handling logic on iOS to fix an issue with `prepareForVideoRecording` not awaiting for the audio permission request result. diff --git a/packages/camera/camera/example/lib/main.dart b/packages/camera/camera/example/lib/main.dart index c0181a5d36a1..2f208a9444c6 100644 --- a/packages/camera/camera/example/lib/main.dart +++ b/packages/camera/camera/example/lib/main.dart @@ -651,8 +651,6 @@ class _CameraExampleHomeState extends State imageFormatGroup: ImageFormatGroup.jpeg, ); - controller = cameraController; - // If the controller is updated then update the UI. cameraController.addListener(() { if (mounted) { @@ -660,7 +658,8 @@ class _CameraExampleHomeState extends State } if (cameraController.value.hasError) { showInSnackBar( - 'Camera error ${cameraController.value.errorDescription}'); + 'Camera error ${cameraController.value.errorDescription}', + ); } }); @@ -668,15 +667,14 @@ class _CameraExampleHomeState extends State await cameraController.initialize(); await Future.wait(>[ // The exposure mode is currently not supported on the web. - ...!kIsWeb - ? >[ - cameraController.getMinExposureOffset().then( - (double value) => _minAvailableExposureOffset = value), - cameraController - .getMaxExposureOffset() - .then((double value) => _maxAvailableExposureOffset = value) - ] - : >[], + if (!kIsWeb) ...>[ + cameraController + .getMinExposureOffset() + .then((double value) => _minAvailableExposureOffset = value), + cameraController + .getMaxExposureOffset() + .then((double value) => _maxAvailableExposureOffset = value), + ], cameraController .getMaxZoomLevel() .then((double value) => _maxAvailableZoom = value), @@ -684,6 +682,14 @@ class _CameraExampleHomeState extends State .getMinZoomLevel() .then((double value) => _minAvailableZoom = value), ]); + // `controller` needs to be set until it's fully initialized to avoid a + // race condition when the lifecycle callback is being called and creates + // a new `controller`. This happens when the camera permission dialog + // dismisses at the first run, which triggers `didChangeAppLifecycleState` + // that disposes and re-creates the controller. Switching controllers in a + // short circumstance might cause the camera preview flashes or make the + // state hard to manage. + controller = cameraController; } on CameraException catch (e) { switch (e.code) { case 'CameraAccessDenied': diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index aca6bebbe066..8397bfeaca98 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing Dart. repository: https://github.com/flutter/plugins/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.6 +version: 0.9.6+1 environment: sdk: ">=2.14.0 <3.0.0"