Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/local_auth/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
6 changes: 6 additions & 0 deletions packages/local_auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ Update your project's `AndroidManifest.xml` file to include the
<manifest>
```

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) 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

You can set the `stickyAuth` option on the plugin to true so that plugin does not
Expand Down
2 changes: 1 addition & 1 deletion packages/local_auth/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ rootProject.allprojects {
apply plugin: 'com.android.library'

android {
compileSdkVersion 28
compileSdkVersion 29

defaultConfig {
minSdkVersion 16
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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 =
Expand All @@ -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);
}
Expand All @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -87,21 +88,30 @@ public void onError(String code, String error) {
authenticationHelper.authenticate();
} else if (call.method.equals("getAvailableBiometrics")) {
try {
Activity activity = registrar.activity();
if (activity == null || activity.isFinishing()) {
result.error("no_activity", "local_auth plugin requires a foreground activity", null);
return;
}
ArrayList<String> biometrics = new ArrayList<String>();
FingerprintManagerCompat fingerprintMgr =
FingerprintManagerCompat.from(registrar.activity());
if (fingerprintMgr.isHardwareDetected()) {
if (fingerprintMgr.hasEnrolledFingerprints()) {
PackageManager packageManager = activity.getPackageManager();
if (Build.VERSION.SDK_INT >= 23) {
if (packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
biometrics.add("fingerprint");
} else {
biometrics.add("undefined");
}
}
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);
}

} else {
result.notImplemented();
}
Expand Down
2 changes: 1 addition & 1 deletion packages/local_auth/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for Android and iOS device authentication sensors
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.5.2+4
version: 0.5.3

flutter:
plugin:
Expand Down