From eeaa591487e7611fad1ba28383d5cdba34a7f23d Mon Sep 17 00:00:00 2001 From: Karan Rawal Date: Tue, 3 Sep 2019 18:06:34 +0530 Subject: [PATCH 1/4] [local_auth] Added api to cancel android fingerprint authentication. --- packages/local_auth/CHANGELOG.md | 4 ++++ .../localauth/AuthenticationHelper.java | 12 +++++++++- .../plugins/localauth/LocalAuthPlugin.java | 22 ++++++++++++++++++- packages/local_auth/example/lib/main.dart | 21 +++++++++++++++--- packages/local_auth/lib/local_auth.dart | 13 +++++++++++ packages/local_auth/pubspec.yaml | 2 +- 6 files changed, 68 insertions(+), 6 deletions(-) diff --git a/packages/local_auth/CHANGELOG.md b/packages/local_auth/CHANGELOG.md index 1988028a1f9d..9d133c1313ae 100644 --- a/packages/local_auth/CHANGELOG.md +++ b/packages/local_auth/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.4 + +* Added ability to stop authentication (For Android). + ## 0.5.3 * Add face id detection as well by not relying on FingerprintCompat. 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 46d7bf3dec9a..dde6e5ce5079 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 @@ interface AuthCompletionHandler { private final boolean isAuthSticky; private final UiThreadExecutor uiThreadExecutor; private boolean activityPaused = false; + private BiometricPrompt biometricPrompt; public AuthenticationHelper( FragmentActivity activity, MethodCall call, AuthCompletionHandler completionHandler) { @@ -83,7 +84,16 @@ public AuthenticationHelper( /** 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 ae69942c8229..d3a0136a0cd9 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) { @@ -59,7 +60,7 @@ public void onMethodCall(MethodCall call, final Result result) { null); return; } - AuthenticationHelper authenticationHelper = + authenticationHelper = new AuthenticationHelper( (FragmentActivity) activity, call, @@ -112,8 +113,27 @@ public void onError(String code, String error) { } 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 feeb5789f343..26dccb750289 100644 --- a/packages/local_auth/example/lib/main.dart +++ b/packages/local_auth/example/lib/main.dart @@ -21,6 +21,7 @@ class _MyAppState extends State { bool _canCheckBiometrics; List _availableBiometrics; String _authorized = 'Not Authorized'; + bool _isAuthenticating = false; Future _checkBiometrics() async { bool canCheckBiometrics; @@ -53,20 +54,33 @@ class _MyAppState extends State { Future _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 @@ class _MyAppState extends State { ), 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 d5f2ac7c4bae..1de552336d11 100644 --- a/packages/local_auth/lib/local_auth.dart +++ b/packages/local_auth/lib/local_auth.dart @@ -76,6 +76,19 @@ class LocalAuthentication { 'authenticateWithBiometrics', args); } + /// Returns true if auth was cancelled successfully. + /// Returns false if there was some error or no auth in progress. + /// + /// Returns [Future] bool true or false: + Future stopAuthentication() { + if (Platform.isAndroid) { + return _channel.invokeMethod('stopAuthentication'); + } + final Future future = Future(() => true); + Completer().complete(future); + return future; + } + /// 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 286d7aa73871..b95215e4b52e 100644 --- a/packages/local_auth/pubspec.yaml +++ b/packages/local_auth/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Android and iOS device authentication sensors such as Fingerprint Reader and Touch ID. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/local_auth -version: 0.5.3 +version: 0.5.4 flutter: plugin: From a8a84f9c9f791f35a733fdfa685eee63f80ffd67 Mon Sep 17 00:00:00 2001 From: Karan Rawal Date: Tue, 3 Sep 2019 18:13:18 +0530 Subject: [PATCH 2/4] [local_auth] Updated readme. --- packages/local_auth/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/local_auth/README.md b/packages/local_auth/README.md index 9cb56e619b24..ca2aa49bed23 100644 --- a/packages/local_auth/README.md +++ b/packages/local_auth/README.md @@ -91,6 +91,16 @@ await localAuth.authenticateWithBiometrics( ``` +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. From ca88f2662692e0de04f56c32f0c33b074977bdb8 Mon Sep 17 00:00:00 2001 From: Karan Rawal Date: Thu, 26 Sep 2019 11:55:48 +0530 Subject: [PATCH 3/4] Fixed Platform.isAndroid issue. --- packages/local_auth/lib/local_auth.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/local_auth/lib/local_auth.dart b/packages/local_auth/lib/local_auth.dart index 1de552336d11..7ff14b14f76d 100644 --- a/packages/local_auth/lib/local_auth.dart +++ b/packages/local_auth/lib/local_auth.dart @@ -63,7 +63,7 @@ class LocalAuthentication { }; if (Platform.isIOS) { args.addAll(iOSAuthStrings.args); - } else if (Platform.isAndroid) { + } else if (Platform.operatingSystem == "android") { args.addAll(androidAuthStrings.args); } else { throw PlatformException( @@ -81,7 +81,7 @@ class LocalAuthentication { /// /// Returns [Future] bool true or false: Future stopAuthentication() { - if (Platform.isAndroid) { + if (Platform.operatingSystem == "android") { return _channel.invokeMethod('stopAuthentication'); } final Future future = Future(() => true); From 2ed420b3792f0ef8fef0e40650fb685143be0547 Mon Sep 17 00:00:00 2001 From: Karan Rawal Date: Fri, 25 Oct 2019 12:46:19 +0530 Subject: [PATCH 4/4] [local_auth] Fixed auth PR reviews. --- packages/local_auth/CHANGELOG.md | 2 +- .../java/io/flutter/plugins/localauth/LocalAuthPlugin.java | 3 ++- packages/local_auth/lib/local_auth.dart | 5 ++--- packages/local_auth/pubspec.yaml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/local_auth/CHANGELOG.md b/packages/local_auth/CHANGELOG.md index 71b062a71a13..8c4a001b4b15 100644 --- a/packages/local_auth/CHANGELOG.md +++ b/packages/local_auth/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.6.0+3 +## 0.6.1 * Added ability to stop authentication (For Android). 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 d3a0136a0cd9..6a8bd9e20e53 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 @@ -38,7 +38,7 @@ private LocalAuthPlugin(Registrar registrar) { @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 @@ -60,6 +60,7 @@ public void onMethodCall(MethodCall call, final Result result) { null); return; } + authInProgress.set(true); authenticationHelper = new AuthenticationHelper( (FragmentActivity) activity, diff --git a/packages/local_auth/lib/local_auth.dart b/packages/local_auth/lib/local_auth.dart index 62ec8f2aae60..31c1a41d0266 100644 --- a/packages/local_auth/lib/local_auth.dart +++ b/packages/local_auth/lib/local_auth.dart @@ -91,6 +91,7 @@ class LocalAuthentication { } /// 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: @@ -98,9 +99,7 @@ class LocalAuthentication { if (_platform.isAndroid) { return _channel.invokeMethod('stopAuthentication'); } - final Future future = Future(() => true); - Completer().complete(future); - return future; + return Future.sync(() => true); } /// Returns true if device is capable of checking biometrics diff --git a/packages/local_auth/pubspec.yaml b/packages/local_auth/pubspec.yaml index 38ed72d23422..13d9f7bed24c 100644 --- a/packages/local_auth/pubspec.yaml +++ b/packages/local_auth/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Android and iOS device authentication sensors such as Fingerprint Reader and Touch ID. author: Flutter Team 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 @@ dependencies: 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: