From e0308b3cd595e308bbd43068c3e5bc16c63357e3 Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Wed, 17 Jul 2019 09:09:29 -0700 Subject: [PATCH 1/4] Fix the typo in the suppresswarnings qualifier --- packages/connectivity/CHANGELOG.md | 4 ++++ .../io/flutter/plugins/connectivity/ConnectivityPlugin.java | 2 +- packages/connectivity/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/connectivity/CHANGELOG.md b/packages/connectivity/CHANGELOG.md index 0af6ccc2e487..6bc9f4a24be6 100644 --- a/packages/connectivity/CHANGELOG.md +++ b/packages/connectivity/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.3+6 + +* [Android] Fix the invalid suppression check (it should be "deprecation" not "deprecated"). + ## 0.4.3+5 * [Android] Added API 29 support for `check()`. diff --git a/packages/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java b/packages/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java index d3187ba8eed1..dac720b0450c 100644 --- a/packages/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java +++ b/packages/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java @@ -84,7 +84,7 @@ private String getNetworkType(ConnectivityManager manager) { return getNetworkTypeLegacy(manager); } - @SuppressWarnings("deprecated") + @SuppressWarnings("deprecation") private String getNetworkTypeLegacy(ConnectivityManager manager) { // handle type for Android versions less than Android 9 NetworkInfo info = manager.getActiveNetworkInfo(); diff --git a/packages/connectivity/pubspec.yaml b/packages/connectivity/pubspec.yaml index 58bbf833275c..33c8e4d94595 100644 --- a/packages/connectivity/pubspec.yaml +++ b/packages/connectivity/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for discovering the state of the network (WiFi & mobile/cellular) connectivity on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/connectivity -version: 0.4.3+5 +version: 0.4.3+6 flutter: plugin: From 2b85df6fc85e22fc1e503ba9313f165943bbe9ac Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Thu, 1 Aug 2019 16:12:37 -0700 Subject: [PATCH 2/4] Add Face unlock support --- packages/local_auth/CHANGELOG.md | 4 ++ packages/local_auth/README.md | 6 +++ .../localauth/AuthenticationHelper.java | 47 ++++++++----------- .../plugins/localauth/LocalAuthPlugin.java | 30 +++++++----- packages/local_auth/pubspec.yaml | 2 +- 5 files changed, 49 insertions(+), 40 deletions(-) diff --git a/packages/local_auth/CHANGELOG.md b/packages/local_auth/CHANGELOG.md index fbbd49351d62..1988028a1f9d 100644 --- a/packages/local_auth/CHANGELOG.md +++ b/packages/local_auth/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.3 + +* Add face id detection as well by not relying on FingerprintCompat. + ## 0.5.2+4 * Update README to fix syntax error. diff --git a/packages/local_auth/README.md b/packages/local_auth/README.md index 3a429be8feea..e1465fa7b133 100644 --- a/packages/local_auth/README.md +++ b/packages/local_auth/README.md @@ -142,6 +142,12 @@ Update your project's `AndroidManifest.xml` file to include the ``` +On Android, you can only check for existence of fingerprint hardware prior +to API 29 (Android Q). Therefore, if you would like to support other biometrics +types (such as face scanning), *do not* call `getAvailableBiometrics`. Simply call +`authenticateWithBiometrics`. This will return an error if there was no hardware +available. + ## Sticky Auth You can set the `stickyAuth` option on the plugin to true so that plugin does not 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 b265dbda1a67..37aff73dfb10 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 @@ -7,7 +7,6 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.Application; -import android.app.KeyguardManager; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; @@ -21,7 +20,6 @@ import android.view.View; import android.widget.TextView; import androidx.biometric.BiometricPrompt; -import androidx.core.hardware.fingerprint.FingerprintManagerCompat; import androidx.fragment.app.FragmentActivity; import io.flutter.plugin.common.MethodCall; import java.util.concurrent.Executor; @@ -60,8 +58,6 @@ interface AuthCompletionHandler { private final FragmentActivity activity; private final AuthCompletionHandler completionHandler; - private final KeyguardManager keyguardManager; - private final FingerprintManagerCompat fingerprintManager; private final MethodCall call; private final BiometricPrompt.PromptInfo promptInfo; private final boolean isAuthSticky; @@ -73,8 +69,6 @@ public AuthenticationHelper( this.activity = activity; this.completionHandler = completionHandler; this.call = call; - this.keyguardManager = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE); - this.fingerprintManager = FingerprintManagerCompat.from(activity); this.isAuthSticky = call.argument("stickyAuth"); this.uiThreadExecutor = new UiThreadExecutor(); this.promptInfo = @@ -86,28 +80,8 @@ public AuthenticationHelper( .build(); } - public void authenticate() { - if (fingerprintManager.isHardwareDetected()) { - if (keyguardManager.isKeyguardSecure() && fingerprintManager.hasEnrolledFingerprints()) { - start(); - } else { - if (call.argument("useErrorDialogs")) { - showGoToSettingsDialog(); - } else if (!keyguardManager.isKeyguardSecure()) { - completionHandler.onError( - "PasscodeNotSet", - "Phone not secured by PIN, pattern or password, or SIM is currently locked."); - } else { - completionHandler.onError("NotEnrolled", "No fingerprint enrolled on this device."); - } - } - } else { - completionHandler.onError("NotAvailable", "Fingerprint is not available on this device."); - } - } - /** Start the fingerprint listener. */ - private void start() { + public void authenticate() { activity.getApplication().registerActivityLifecycleCallbacks(this); new BiometricPrompt(activity, uiThreadExecutor, this).authenticate(promptInfo); } @@ -121,6 +95,25 @@ private void stop() { @Override public void onAuthenticationError(int errorCode, CharSequence errString) { switch (errorCode) { + // TODO(mehmetf): Re-enable when biometric alpha05 is released. + // https://developer.android.com/jetpack/androidx/releases/biometric + // case BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL: + // completionHandler.onError( + // "PasscodeNotSet", + // "Phone not secured by PIN, pattern or password, or SIM is currently locked."); + // break; + case BiometricPrompt.ERROR_NO_SPACE: + case BiometricPrompt.ERROR_NO_BIOMETRICS: + if (call.argument("useErrorDialogs")) { + showGoToSettingsDialog(); + return; + } + completionHandler.onError("NotEnrolled", "No Biometrics enrolled on this device."); + break; + case BiometricPrompt.ERROR_HW_UNAVAILABLE: + case BiometricPrompt.ERROR_HW_NOT_PRESENT: + completionHandler.onError("NotAvailable", "Biometrics is not available on this device."); + break; case BiometricPrompt.ERROR_LOCKOUT: completionHandler.onError( "LockedOut", 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 9c5f8bd7d014..2809b4956e84 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 @@ -87,23 +87,29 @@ public void onError(String code, String error) { authenticationHelper.authenticate(); } else if (call.method.equals("getAvailableBiometrics")) { try { - ArrayList biometrics = new ArrayList(); - FingerprintManagerCompat fingerprintMgr = - FingerprintManagerCompat.from(registrar.activity()); - if (fingerprintMgr.isHardwareDetected()) { - if (fingerprintMgr.hasEnrolledFingerprints()) { - biometrics.add("fingerprint"); - } else { - biometrics.add("undefined"); - } - } - result.success(biometrics); + // TODO(mehmetf): Add check using biometric manager when it is available in androidx. + checkUsingFingerPrintManager(result); } catch (Exception e) { result.error("no_biometrics_available", e.getMessage(), null); } - } else { result.notImplemented(); } } + + // We don't return an error here because the point is to check whether the device has + // any biometric detection available. If there is none, we return an empty set. If there's + // one but it is not setup correctly, we return "unknown". + private void checkUsingFingerPrintManager(final Result result) { + ArrayList biometrics = new ArrayList(); + FingerprintManagerCompat fingerprintMgr = FingerprintManagerCompat.from(registrar.activity()); + if (fingerprintMgr.isHardwareDetected()) { + if (fingerprintMgr.hasEnrolledFingerprints()) { + biometrics.add("fingerprint"); + } else { + biometrics.add("unknown"); + } + } + result.success(biometrics); + } } diff --git a/packages/local_auth/pubspec.yaml b/packages/local_auth/pubspec.yaml index 7531d03a9e03..286d7aa73871 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.2+4 +version: 0.5.3 flutter: plugin: From e602628993cbd892da4c583b1b0772e559f49282 Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Fri, 2 Aug 2019 14:23:36 -0700 Subject: [PATCH 3/4] Fix formatting --- .../plugins/localauth/AuthenticationHelper.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 37aff73dfb10..46d7bf3dec9a 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 @@ -95,13 +95,13 @@ private void stop() { @Override public void onAuthenticationError(int errorCode, CharSequence errString) { switch (errorCode) { - // TODO(mehmetf): Re-enable when biometric alpha05 is released. - // https://developer.android.com/jetpack/androidx/releases/biometric - // case BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL: - // completionHandler.onError( - // "PasscodeNotSet", - // "Phone not secured by PIN, pattern or password, or SIM is currently locked."); - // break; + // TODO(mehmetf): Re-enable when biometric alpha05 is released. + // https://developer.android.com/jetpack/androidx/releases/biometric + // case BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL: + // completionHandler.onError( + // "PasscodeNotSet", + // "Phone not secured by PIN, pattern or password, or SIM is currently locked."); + // break; case BiometricPrompt.ERROR_NO_SPACE: case BiometricPrompt.ERROR_NO_BIOMETRICS: if (call.argument("useErrorDialogs")) { From 247e8fd21e84aaaeff470764578da7e3123c0f5e Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Fri, 2 Aug 2019 17:36:42 -0700 Subject: [PATCH 4/4] Check for all types of biometrics API 29 and above. --- packages/local_auth/README.md | 8 ++-- packages/local_auth/android/build.gradle | 2 +- .../plugins/localauth/LocalAuthPlugin.java | 42 ++++++++++--------- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/packages/local_auth/README.md b/packages/local_auth/README.md index e1465fa7b133..9cb56e619b24 100644 --- a/packages/local_auth/README.md +++ b/packages/local_auth/README.md @@ -142,11 +142,11 @@ Update your project's `AndroidManifest.xml` file to include the ``` -On Android, you can only check for existence of fingerprint hardware prior +On Android, you can check only for existence of fingerprint hardware prior to API 29 (Android Q). Therefore, if you would like to support other biometrics -types (such as face scanning), *do not* call `getAvailableBiometrics`. Simply call -`authenticateWithBiometrics`. This will return an error if there was no hardware -available. +types (such as face scanning) and you want to support SDKs lower than Q, +*do not* call `getAvailableBiometrics`. Simply call `authenticateWithBiometrics`. +This will return an error if there was no hardware available. ## Sticky Auth diff --git a/packages/local_auth/android/build.gradle b/packages/local_auth/android/build.gradle index 4da3597692c1..142b606405c4 100644 --- a/packages/local_auth/android/build.gradle +++ b/packages/local_auth/android/build.gradle @@ -35,7 +35,7 @@ rootProject.allprojects { apply plugin: 'com.android.library' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 16 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 2809b4956e84..ae69942c8229 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 @@ -5,7 +5,8 @@ package io.flutter.plugins.localauth; import android.app.Activity; -import androidx.core.hardware.fingerprint.FingerprintManagerCompat; +import android.content.pm.PackageManager; +import android.os.Build; import androidx.fragment.app.FragmentActivity; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; @@ -87,8 +88,27 @@ public void onError(String code, String error) { authenticationHelper.authenticate(); } else if (call.method.equals("getAvailableBiometrics")) { try { - // TODO(mehmetf): Add check using biometric manager when it is available in androidx. - checkUsingFingerPrintManager(result); + Activity activity = registrar.activity(); + if (activity == null || activity.isFinishing()) { + result.error("no_activity", "local_auth plugin requires a foreground activity", null); + return; + } + ArrayList biometrics = new ArrayList(); + PackageManager packageManager = activity.getPackageManager(); + if (Build.VERSION.SDK_INT >= 23) { + if (packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { + biometrics.add("fingerprint"); + } + } + if (Build.VERSION.SDK_INT >= 29) { + if (packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) { + biometrics.add("face"); + } + if (packageManager.hasSystemFeature(PackageManager.FEATURE_IRIS)) { + biometrics.add("iris"); + } + } + result.success(biometrics); } catch (Exception e) { result.error("no_biometrics_available", e.getMessage(), null); } @@ -96,20 +116,4 @@ public void onError(String code, String error) { result.notImplemented(); } } - - // We don't return an error here because the point is to check whether the device has - // any biometric detection available. If there is none, we return an empty set. If there's - // one but it is not setup correctly, we return "unknown". - private void checkUsingFingerPrintManager(final Result result) { - ArrayList biometrics = new ArrayList(); - FingerprintManagerCompat fingerprintMgr = FingerprintManagerCompat.from(registrar.activity()); - if (fingerprintMgr.isHardwareDetected()) { - if (fingerprintMgr.hasEnrolledFingerprints()) { - biometrics.add("fingerprint"); - } else { - biometrics.add("unknown"); - } - } - result.success(biometrics); - } }