From 9af41008a2d347933bf9e6a329f2a00761b77258 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 8 Oct 2020 18:40:33 +0200 Subject: [PATCH 1/5] Add extra null check and update README --- packages/camera/CHANGELOG.md | 5 +++++ packages/camera/README.md | 21 +++++++++++++++++++ .../io/flutter/plugins/camera/Camera.java | 4 +++- packages/camera/pubspec.yaml | 2 +- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/camera/CHANGELOG.md b/packages/camera/CHANGELOG.md index bd075f490e90..ebf654f49b22 100644 --- a/packages/camera/CHANGELOG.md +++ b/packages/camera/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.5.8+11 + +* Fix rare nullptr exception on Android. +* Updated README.md with information about handling App lifecycle changes. + ## 0.5.8+10 * Suppress the `deprecated_member_use` warning in the example app for `ScaffoldMessenger.showSnackBar`. diff --git a/packages/camera/README.md b/packages/camera/README.md index fbd73929e6de..c56ed0dfe349 100644 --- a/packages/camera/README.md +++ b/packages/camera/README.md @@ -41,6 +41,27 @@ Change the minimum Android sdk version to 21 (or higher) in your `android/app/bu minSdkVersion 21 ``` +### Handling Lifecycle states + +As of version [0.5.0](https://github.com/flutter/plugins/blob/master/packages/camera/CHANGELOG.md#050) of the camera plugin, lifecycle changes are no longer handled by the plugin. This means developers are now responsible to control camera resources when the lifecycle state is updated. Failure to do so might lead to unexpected behavior (for example as described in issue [#39109](https://github.com/flutter/flutter/issues/39109)). Handling lifecycle changes can be done by overriding the `didChangeAppLifecycleState` method like so: + +```dart + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + // App state changed before we got the chance to initialize. + if (controller == null || !controller.value.isInitialized) { + return; + } + if (state == AppLifecycleState.inactive) { + controller?.dispose(); + } else if (state == AppLifecycleState.resumed) { + if (controller != null) { + onNewCameraSelected(controller.description); + } + } + } +``` + ### Example Here is a small example flutter app displaying a full screen camera preview. diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index 63e4d03e982a..defa32c2e4aa 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -408,8 +408,10 @@ public void resumeVideoRecording(@NonNull final Result result) { result.success(null); } - + public void startPreview() throws CameraAccessException { + if (pictureImageReader == null || pictureImageReader.getSurface() == null) return; + createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface()); } diff --git a/packages/camera/pubspec.yaml b/packages/camera/pubspec.yaml index b581135967f1..7a2b187098ef 100644 --- a/packages/camera/pubspec.yaml +++ b/packages/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.5.8+10 +version: 0.5.8+11 homepage: https://github.com/flutter/plugins/tree/master/packages/camera From b278ae917f7ac8611641f112150cddb6ddaa2a56 Mon Sep 17 00:00:00 2001 From: panmari Date: Fri, 26 Jun 2020 10:47:52 +0200 Subject: [PATCH 2/5] [camera] Adding check for null before creating capture session. Occasionally leads to NullPointerException (potentially due to some race condition, hard to reproduce deterministically). Example stack trace: E/AndroidRuntime( 5679): java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Surface android.media.ImageReader.getSurface()' on a null object reference E/AndroidRuntime( 5679): at io.flutter.plugins.camera.Camera.startPreview(Camera.java:424) E/AndroidRuntime( 5679): at io.flutter.plugins.camera.Camera$2.onOpened(Camera.java:160) E/AndroidRuntime( 5679): at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:145) E/AndroidRuntime( 5679): at android.os.Handler.handleCallback(Handler.java:883) E/AndroidRuntime( 5679): at android.os.Handler.dispatchMessage(Handler.java:100) E/AndroidRuntime( 5679): at android.os.Looper.loop(Looper.java:214) E/AndroidRuntime( 5679): at android.app.ActivityThread.main(ActivityThread.java:7356) E/AndroidRuntime( 5679): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime( 5679): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) E/AndroidRuntime( 5679): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) --- .../src/main/java/io/flutter/plugins/camera/Camera.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index defa32c2e4aa..8f8436453607 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -410,9 +410,17 @@ public void resumeVideoRecording(@NonNull final Result result) { } public void startPreview() throws CameraAccessException { +<<<<<<< HEAD if (pictureImageReader == null || pictureImageReader.getSurface() == null) return; createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface()); +||||||| constructed merge base + createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface()); +======= + if (pictureImageReader != null) { + createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface()); + } +>>>>>>> [camera] Adding check for null before creating capture session. } public void startPreviewWithImageStream(EventChannel imageStreamChannel) From de546b6929313ac6ce6b673dda579cc7269988b6 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 8 Oct 2020 14:44:40 +0200 Subject: [PATCH 3/5] Invert if and add lifecycle documentation --- .../src/main/java/io/flutter/plugins/camera/Camera.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index 8f8436453607..defa32c2e4aa 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -410,17 +410,9 @@ public void resumeVideoRecording(@NonNull final Result result) { } public void startPreview() throws CameraAccessException { -<<<<<<< HEAD if (pictureImageReader == null || pictureImageReader.getSurface() == null) return; createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface()); -||||||| constructed merge base - createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface()); -======= - if (pictureImageReader != null) { - createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface()); - } ->>>>>>> [camera] Adding check for null before creating capture session. } public void startPreviewWithImageStream(EventChannel imageStreamChannel) From 1e6caf7e255982e9127ac1638e3496b81e1616f2 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 8 Oct 2020 18:51:05 +0200 Subject: [PATCH 4/5] Fix formattin issues --- .../android/src/main/java/io/flutter/plugins/camera/Camera.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index defa32c2e4aa..143d78c23ebd 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -408,7 +408,7 @@ public void resumeVideoRecording(@NonNull final Result result) { result.success(null); } - + public void startPreview() throws CameraAccessException { if (pictureImageReader == null || pictureImageReader.getSurface() == null) return; From 8557845c09f1be9baff261632bc0b463139afdba Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Wed, 14 Oct 2020 17:09:52 +0200 Subject: [PATCH 5/5] Fix formatting issues --- .../android/src/main/java/io/flutter/plugins/camera/Camera.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java index 143d78c23ebd..2384393c7d2b 100644 --- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -411,7 +411,7 @@ public void resumeVideoRecording(@NonNull final Result result) { public void startPreview() throws CameraAccessException { if (pictureImageReader == null || pictureImageReader.getSurface() == null) return; - + createCaptureSession(CameraDevice.TEMPLATE_PREVIEW, pictureImageReader.getSurface()); }