Skip to content

Commit ffb7903

Browse files
karan-rawalmehmetf
authored andcommitted
[local_auth] Api to stop authentication (flutter#2111)
1 parent 4c793a3 commit ffb7903

File tree

7 files changed

+80
-8
lines changed

7 files changed

+80
-8
lines changed

packages/local_auth/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.6.1
2+
3+
* Added ability to stop authentication (For Android).
4+
15
## 0.6.0+3
26

37
* Remove AndroidX warnings.

packages/local_auth/README.md

+10
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,16 @@ await localAuth.authenticateWithBiometrics(
9191
9292
```
9393

94+
If needed, you can manually stop authentication for android:
95+
96+
```dart
97+
98+
void _cancelAuthentication() {
99+
localAuth.stopAuthentication();
100+
}
101+
102+
```
103+
94104
### Exceptions
95105

96106
There are 6 types of exceptions: PasscodeNotSet, NotEnrolled, NotAvailable, OtherOperatingSystem, LockedOut and PermanentlyLockedOut.

packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ interface AuthCompletionHandler {
6363
private final boolean isAuthSticky;
6464
private final UiThreadExecutor uiThreadExecutor;
6565
private boolean activityPaused = false;
66+
private BiometricPrompt biometricPrompt;
6667

6768
public AuthenticationHelper(
6869
FragmentActivity activity, MethodCall call, AuthCompletionHandler completionHandler) {
@@ -84,7 +85,16 @@ public AuthenticationHelper(
8485
/** Start the fingerprint listener. */
8586
public void authenticate() {
8687
activity.getApplication().registerActivityLifecycleCallbacks(this);
87-
new BiometricPrompt(activity, uiThreadExecutor, this).authenticate(promptInfo);
88+
biometricPrompt = new BiometricPrompt(activity, uiThreadExecutor, this);
89+
biometricPrompt.authenticate(promptInfo);
90+
}
91+
92+
/** Cancels the fingerprint authentication. */
93+
public void stopAuthentication() {
94+
if (biometricPrompt != null) {
95+
biometricPrompt.cancelAuthentication();
96+
biometricPrompt = null;
97+
}
8898
}
8999

90100
/** Stops the fingerprint listener. */

packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java

+23-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
public class LocalAuthPlugin implements MethodCallHandler {
2323
private final Registrar registrar;
2424
private final AtomicBoolean authInProgress = new AtomicBoolean(false);
25+
private AuthenticationHelper authenticationHelper;
2526

2627
/** Plugin registration. */
2728
public static void registerWith(Registrar registrar) {
@@ -37,7 +38,7 @@ private LocalAuthPlugin(Registrar registrar) {
3738
@Override
3839
public void onMethodCall(MethodCall call, final Result result) {
3940
if (call.method.equals("authenticateWithBiometrics")) {
40-
if (!authInProgress.compareAndSet(false, true)) {
41+
if (authInProgress.get()) {
4142
// Apps should not invoke another authentication request while one is in progress,
4243
// so we classify this as an error condition. If we ever find a legitimate use case for
4344
// this, we can try to cancel the ongoing auth and start a new one but for now, not worth
@@ -59,7 +60,8 @@ public void onMethodCall(MethodCall call, final Result result) {
5960
null);
6061
return;
6162
}
62-
AuthenticationHelper authenticationHelper =
63+
authInProgress.set(true);
64+
authenticationHelper =
6365
new AuthenticationHelper(
6466
(FragmentActivity) activity,
6567
call,
@@ -112,8 +114,27 @@ public void onError(String code, String error) {
112114
} catch (Exception e) {
113115
result.error("no_biometrics_available", e.getMessage(), null);
114116
}
117+
} else if (call.method.equals(("stopAuthentication"))) {
118+
stopAuthentication(result);
115119
} else {
116120
result.notImplemented();
117121
}
118122
}
123+
124+
/*
125+
Stops the authentication if in progress.
126+
*/
127+
private void stopAuthentication(Result result) {
128+
try {
129+
if (authenticationHelper != null && authInProgress.get()) {
130+
authenticationHelper.stopAuthentication();
131+
authenticationHelper = null;
132+
result.success(true);
133+
return;
134+
}
135+
result.success(false);
136+
} catch (Exception e) {
137+
result.success(false);
138+
}
139+
}
119140
}

packages/local_auth/example/lib/main.dart

+18-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class _MyAppState extends State<MyApp> {
2121
bool _canCheckBiometrics;
2222
List<BiometricType> _availableBiometrics;
2323
String _authorized = 'Not Authorized';
24+
bool _isAuthenticating = false;
2425

2526
Future<void> _checkBiometrics() async {
2627
bool canCheckBiometrics;
@@ -53,20 +54,33 @@ class _MyAppState extends State<MyApp> {
5354
Future<void> _authenticate() async {
5455
bool authenticated = false;
5556
try {
57+
setState(() {
58+
_isAuthenticating = true;
59+
_authorized = 'Authenticating';
60+
});
5661
authenticated = await auth.authenticateWithBiometrics(
5762
localizedReason: 'Scan your fingerprint to authenticate',
5863
useErrorDialogs: true,
5964
stickyAuth: true);
65+
setState(() {
66+
_isAuthenticating = false;
67+
_authorized = 'Authenticating';
68+
});
6069
} on PlatformException catch (e) {
6170
print(e);
6271
}
6372
if (!mounted) return;
6473

74+
final String message = authenticated ? 'Authorized' : 'Not Authorized';
6575
setState(() {
66-
_authorized = authenticated ? 'Authorized' : 'Not Authorized';
76+
_authorized = message;
6777
});
6878
}
6979

80+
void _cancelAuthentication() {
81+
auth.stopAuthentication();
82+
}
83+
7084
@override
7185
Widget build(BuildContext context) {
7286
return MaterialApp(
@@ -91,8 +105,9 @@ class _MyAppState extends State<MyApp> {
91105
),
92106
Text('Current State: $_authorized\n'),
93107
RaisedButton(
94-
child: const Text('Authenticate'),
95-
onPressed: _authenticate,
108+
child: Text(_isAuthenticating ? 'Cancel' : 'Authenticate'),
109+
onPressed:
110+
_isAuthenticating ? _cancelAuthentication : _authenticate,
96111
)
97112
])),
98113
));

packages/local_auth/lib/local_auth.dart

+12
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ class LocalAuthentication {
9090
'authenticateWithBiometrics', args);
9191
}
9292

93+
/// Returns true if auth was cancelled successfully.
94+
/// This api only works for Android.
95+
/// Returns false if there was some error or no auth in progress.
96+
///
97+
/// Returns [Future] bool true or false:
98+
Future<bool> stopAuthentication() {
99+
if (_platform.isAndroid) {
100+
return _channel.invokeMethod<bool>('stopAuthentication');
101+
}
102+
return Future<bool>.sync(() => true);
103+
}
104+
93105
/// Returns true if device is capable of checking biometrics
94106
///
95107
/// Returns a [Future] bool true or false:

packages/local_auth/pubspec.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for Android and iOS device authentication sensors
33
such as Fingerprint Reader and Touch ID.
44
author: Flutter Team <[email protected]>
55
homepage: https://github.com/flutter/plugins/tree/master/packages/local_auth
6-
version: 0.6.0+3
6+
version: 0.6.1
77

88
flutter:
99
plugin:
@@ -16,7 +16,7 @@ dependencies:
1616
sdk: flutter
1717
meta: ^1.0.5
1818
intl: ">=0.15.1 <0.17.0"
19-
platform: ^2.0.0
19+
platform: ^2.0.0
2020

2121
dev_dependencies:
2222
flutter_test:

0 commit comments

Comments
 (0)