[local_auth] Api to stop authentication (#2111)
diff --git a/packages/local_auth/CHANGELOG.md b/packages/local_auth/CHANGELOG.md
index b69e060..0c54edc 100644
--- a/packages/local_auth/CHANGELOG.md
+++ b/packages/local_auth/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.1
+
+* Added ability to stop authentication (For Android).
+
## 0.6.0+3
* Remove AndroidX warnings.
diff --git a/packages/local_auth/README.md b/packages/local_auth/README.md
index 9cb56e6..ca2aa49 100644
--- a/packages/local_auth/README.md
+++ b/packages/local_auth/README.md
@@ -91,6 +91,16 @@
```
+If needed, you can manually stop authentication for android:
+
+```dart
+
+void _cancelAuthentication() {
+ localAuth.stopAuthentication();
+}
+
+```
+
### Exceptions
There are 6 types of exceptions: PasscodeNotSet, NotEnrolled, NotAvailable, OtherOperatingSystem, LockedOut and PermanentlyLockedOut.
diff --git a/packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java b/packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java
index a4ef01b..99dab6d 100644
--- a/packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java
+++ b/packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java
@@ -63,6 +63,7 @@
private final boolean isAuthSticky;
private final UiThreadExecutor uiThreadExecutor;
private boolean activityPaused = false;
+ private BiometricPrompt biometricPrompt;
public AuthenticationHelper(
FragmentActivity activity, MethodCall call, AuthCompletionHandler completionHandler) {
@@ -84,7 +85,16 @@
/** Start the fingerprint listener. */
public void authenticate() {
activity.getApplication().registerActivityLifecycleCallbacks(this);
- new BiometricPrompt(activity, uiThreadExecutor, this).authenticate(promptInfo);
+ biometricPrompt = new BiometricPrompt(activity, uiThreadExecutor, this);
+ biometricPrompt.authenticate(promptInfo);
+ }
+
+ /** Cancels the fingerprint authentication. */
+ public void stopAuthentication() {
+ if (biometricPrompt != null) {
+ biometricPrompt.cancelAuthentication();
+ biometricPrompt = null;
+ }
}
/** Stops the fingerprint listener. */
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 ae69942..6a8bd9e 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
@@ -22,6 +22,7 @@
public class LocalAuthPlugin implements MethodCallHandler {
private final Registrar registrar;
private final AtomicBoolean authInProgress = new AtomicBoolean(false);
+ private AuthenticationHelper authenticationHelper;
/** Plugin registration. */
public static void registerWith(Registrar registrar) {
@@ -37,7 +38,7 @@
@Override
public void onMethodCall(MethodCall call, final Result result) {
if (call.method.equals("authenticateWithBiometrics")) {
- if (!authInProgress.compareAndSet(false, true)) {
+ if (authInProgress.get()) {
// Apps should not invoke another authentication request while one is in progress,
// so we classify this as an error condition. If we ever find a legitimate use case for
// this, we can try to cancel the ongoing auth and start a new one but for now, not worth
@@ -59,7 +60,8 @@
null);
return;
}
- AuthenticationHelper authenticationHelper =
+ authInProgress.set(true);
+ authenticationHelper =
new AuthenticationHelper(
(FragmentActivity) activity,
call,
@@ -112,8 +114,27 @@
} catch (Exception e) {
result.error("no_biometrics_available", e.getMessage(), null);
}
+ } else if (call.method.equals(("stopAuthentication"))) {
+ stopAuthentication(result);
} else {
result.notImplemented();
}
}
+
+ /*
+ Stops the authentication if in progress.
+ */
+ private void stopAuthentication(Result result) {
+ try {
+ if (authenticationHelper != null && authInProgress.get()) {
+ authenticationHelper.stopAuthentication();
+ authenticationHelper = null;
+ result.success(true);
+ return;
+ }
+ result.success(false);
+ } catch (Exception e) {
+ result.success(false);
+ }
+ }
}
diff --git a/packages/local_auth/example/lib/main.dart b/packages/local_auth/example/lib/main.dart
index feeb578..26dccb7 100644
--- a/packages/local_auth/example/lib/main.dart
+++ b/packages/local_auth/example/lib/main.dart
@@ -21,6 +21,7 @@
bool _canCheckBiometrics;
List<BiometricType> _availableBiometrics;
String _authorized = 'Not Authorized';
+ bool _isAuthenticating = false;
Future<void> _checkBiometrics() async {
bool canCheckBiometrics;
@@ -53,20 +54,33 @@
Future<void> _authenticate() async {
bool authenticated = false;
try {
+ setState(() {
+ _isAuthenticating = true;
+ _authorized = 'Authenticating';
+ });
authenticated = await auth.authenticateWithBiometrics(
localizedReason: 'Scan your fingerprint to authenticate',
useErrorDialogs: true,
stickyAuth: true);
+ setState(() {
+ _isAuthenticating = false;
+ _authorized = 'Authenticating';
+ });
} on PlatformException catch (e) {
print(e);
}
if (!mounted) return;
+ final String message = authenticated ? 'Authorized' : 'Not Authorized';
setState(() {
- _authorized = authenticated ? 'Authorized' : 'Not Authorized';
+ _authorized = message;
});
}
+ void _cancelAuthentication() {
+ auth.stopAuthentication();
+ }
+
@override
Widget build(BuildContext context) {
return MaterialApp(
@@ -91,8 +105,9 @@
),
Text('Current State: $_authorized\n'),
RaisedButton(
- child: const Text('Authenticate'),
- onPressed: _authenticate,
+ child: Text(_isAuthenticating ? 'Cancel' : 'Authenticate'),
+ onPressed:
+ _isAuthenticating ? _cancelAuthentication : _authenticate,
)
])),
));
diff --git a/packages/local_auth/lib/local_auth.dart b/packages/local_auth/lib/local_auth.dart
index df69a12..31c1a41 100644
--- a/packages/local_auth/lib/local_auth.dart
+++ b/packages/local_auth/lib/local_auth.dart
@@ -90,6 +90,18 @@
'authenticateWithBiometrics', args);
}
+ /// Returns true if auth was cancelled successfully.
+ /// This api only works for Android.
+ /// Returns false if there was some error or no auth in progress.
+ ///
+ /// Returns [Future] bool true or false:
+ Future<bool> stopAuthentication() {
+ if (_platform.isAndroid) {
+ return _channel.invokeMethod<bool>('stopAuthentication');
+ }
+ return Future<bool>.sync(() => true);
+ }
+
/// Returns true if device is capable of checking biometrics
///
/// Returns a [Future] bool true or false:
diff --git a/packages/local_auth/pubspec.yaml b/packages/local_auth/pubspec.yaml
index 38ed72d..13d9f7b 100644
--- a/packages/local_auth/pubspec.yaml
+++ b/packages/local_auth/pubspec.yaml
@@ -3,7 +3,7 @@
such as Fingerprint Reader and Touch ID.
author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/local_auth
-version: 0.6.0+3
+version: 0.6.1
flutter:
plugin:
@@ -16,7 +16,7 @@
sdk: flutter
meta: ^1.0.5
intl: ">=0.15.1 <0.17.0"
- platform: ^2.0.0
+ platform: ^2.0.0
dev_dependencies:
flutter_test: