[local_auth] Fix activity leak in LocalAuthPlugin (#4449)

diff --git a/packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java b/packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java
index 7ed9a7e..a63e22a 100644
--- a/packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java
+++ b/packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java
@@ -15,6 +15,7 @@
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Build;
 import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
 import androidx.biometric.BiometricManager;
 import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.Lifecycle;
@@ -337,6 +338,7 @@
   @Override
   public void onDetachedFromActivityForConfigChanges() {
     lifecycle = null;
+    activity = null;
   }
 
   @Override
@@ -350,5 +352,11 @@
   public void onDetachedFromActivity() {
     lifecycle = null;
     channel.setMethodCallHandler(null);
+    activity = null;
+  }
+
+  @VisibleForTesting
+  final Activity getActivity() {
+    return activity;
   }
 }
diff --git a/packages/local_auth/android/src/test/java/io/flutter/plugins/localauth/LocalAuthTest.java b/packages/local_auth/android/src/test/java/io/flutter/plugins/localauth/LocalAuthTest.java
index 522185f..41868e6 100644
--- a/packages/local_auth/android/src/test/java/io/flutter/plugins/localauth/LocalAuthTest.java
+++ b/packages/local_auth/android/src/test/java/io/flutter/plugins/localauth/LocalAuthTest.java
@@ -4,9 +4,20 @@
 
 package io.flutter.plugins.localauth;
 
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
+import android.app.Activity;
+import android.content.Context;
+import androidx.lifecycle.Lifecycle;
+import io.flutter.embedding.engine.FlutterEngine;
+import io.flutter.embedding.engine.dart.DartExecutor;
+import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding;
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
+import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference;
 import io.flutter.plugin.common.MethodCall;
 import io.flutter.plugin.common.MethodChannel;
 import org.junit.Test;
@@ -19,4 +30,35 @@
     plugin.onMethodCall(new MethodCall("isDeviceSupported", null), mockResult);
     verify(mockResult).success(false);
   }
+
+  @Test
+  public void onDetachedFromActivity_ShouldReleaseActivity() {
+    final Activity mockActivity = mock(Activity.class);
+    final ActivityPluginBinding mockActivityBinding = mock(ActivityPluginBinding.class);
+    when(mockActivityBinding.getActivity()).thenReturn(mockActivity);
+
+    Context mockContext = mock(Context.class);
+    when(mockActivity.getBaseContext()).thenReturn(mockContext);
+
+    final HiddenLifecycleReference mockLifecycleReference = mock(HiddenLifecycleReference.class);
+    when(mockActivityBinding.getLifecycle()).thenReturn(mockLifecycleReference);
+
+    final Lifecycle mockLifecycle = mock(Lifecycle.class);
+    when(mockLifecycleReference.getLifecycle()).thenReturn(mockLifecycle);
+
+    final FlutterPluginBinding mockPluginBinding = mock(FlutterPluginBinding.class);
+    final FlutterEngine mockFlutterEngine = mock(FlutterEngine.class);
+    when(mockPluginBinding.getFlutterEngine()).thenReturn(mockFlutterEngine);
+
+    DartExecutor mockDartExecutor = mock(DartExecutor.class);
+    when(mockFlutterEngine.getDartExecutor()).thenReturn(mockDartExecutor);
+
+    final LocalAuthPlugin plugin = new LocalAuthPlugin();
+    plugin.onAttachedToEngine(mockPluginBinding);
+    plugin.onAttachedToActivity(mockActivityBinding);
+    assertNotNull(plugin.getActivity());
+
+    plugin.onDetachedFromActivity();
+    assertNull(plugin.getActivity());
+  }
 }