diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md index 256fb9b78c7..5293910342e 100644 --- a/packages/camera/camera_android_camerax/CHANGELOG.md +++ b/packages/camera/camera_android_camerax/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.25+1 + +* Fixes crash on hot restart caused by stale observers. + ## 0.6.25 * Adds support for `MediaSettings.fps` for camera preview, image streaming, and video recording. diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ObserverProxyApi.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ObserverProxyApi.java index 7318091be56..862886c7ac0 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ObserverProxyApi.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ObserverProxyApi.java @@ -29,6 +29,19 @@ public void onChanged(T t) { new ProxyApiRegistrar.FlutterMethodRunnable() { @Override public void run() { + // Check if this observer instance is still in the instance manager. + // During hot restart, old observers may remain attached to LiveData but + // are no longer tracked in the instance manager. + if (!api.getPigeonRegistrar() + .getInstanceManager() + .containsInstance(ObserverImpl.this)) { + android.util.Log.w( + "ObserverProxyApi", + "Ignoring onChanged callback for Observer not in InstanceManager (likely from previous hot restart): " + + ObserverImpl.this); + return; + } + api.onChanged( ObserverImpl.this, t, diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ObserverTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ObserverTest.java index b0ca542e5f3..854f1e384cc 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ObserverTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ObserverTest.java @@ -7,22 +7,43 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import org.junit.Before; import org.junit.Test; public class ObserverTest { + private ObserverProxyApi mockApi; + private TestProxyApiRegistrar registrar; + private ObserverProxyApi.ObserverImpl instance; + + @Before + public void setUp() { + mockApi = mock(ObserverProxyApi.class); + registrar = new TestProxyApiRegistrar(); + when(mockApi.getPigeonRegistrar()).thenReturn(registrar); + instance = new ObserverProxyApi.ObserverImpl<>(mockApi); + } + @Test public void onChanged_makesExpectedCallToDartCallback() { - final ObserverProxyApi mockApi = mock(ObserverProxyApi.class); - when(mockApi.getPigeonRegistrar()).thenReturn(new TestProxyApiRegistrar()); + // Add the observer to the instance manager to simulate normal operation + registrar.getInstanceManager().addDartCreatedInstance(instance, 0); - final ObserverProxyApi.ObserverImpl instance = - new ObserverProxyApi.ObserverImpl<>(mockApi); final String value = "result"; instance.onChanged(value); verify(mockApi).onChanged(eq(instance), eq(value), any()); } + + @Test + public void onChanged_doesNotCallDartCallbackWhenObserverNotInInstanceManager() { + final String value = "result"; + instance.onChanged(value); + + // Verify that the Dart callback is NOT invoked for stale observers + verify(mockApi, never()).onChanged(any(), any(), any()); + } } diff --git a/packages/camera/camera_android_camerax/pubspec.yaml b/packages/camera/camera_android_camerax/pubspec.yaml index 756c856eba0..ca527345509 100644 --- a/packages/camera/camera_android_camerax/pubspec.yaml +++ b/packages/camera/camera_android_camerax/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_android_camerax description: Android implementation of the camera plugin using the CameraX library. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.6.25 +version: 0.6.25+1 environment: sdk: ^3.9.0