Как проверить биометрические предпочтения пользователя через биометрические API?

Как мы все знаем, начиная с Android 9.0, Android представила BiometricPrompt Api, чтобы обеспечить стандартную аутентификацию для растущего диапазона биометрических датчиков (например, отпечатков пальцев,Face ID и т. Д.).

Теперь с этим новым BiometricPrompt Api пользователь может пройти аутентификацию с помощью отпечатка пальца, сканера лица или радужной оболочки (в зависимости от его биометрических предпочтений). BiometricPrompt api позаботится об этом и уведомит нас с помощью различных обратных вызовов.

Ниже мой код для отображения биометрической подсказки.

 biometricPrompt = new BiometricPrompt.Builder(context)
            .setTitle("FingerPrint Authentication")
            .setSubtitle("Login via Fingerprint")
            .setDescription("Touch Fingerprint Sensor")
            .setNegativeButton("Cancel", context.getMainExecutor(),
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            Log.d(TAG,"Cancelled");
                        }
                    })
            .build();

Теперь, если вы видите мой код, я устанавливаю заголовок как Аутентификация по отпечатку пальца. Теперь в настройках устройства, если пользователь установил биометрические предпочтения в качестве идентификатора лица вместо FingerPrint, этот biometicPrompt будет аутентифицировать пользователя через faceID, и датчик отпечатков пальцев не будет работать, даже если пользователь продолжает касаться датчика. Это создало бы путаницу, поскольку биометрический заголовок говорит, что "Аутентификация по отпечатку пальца" и пользователь фактически проходит аутентификацию через faceID

Есть ли способ узнать, какой пользователь биометрических предпочтений выбрал (например, отпечаток пальца или FaceID)? Таким образом, основываясь на этом предпочтении, я могу показать соответствующее сообщение на BiometricPrompt, чтобы пользователь не запутался.

Я уже исследовал все API от BiometricPrompt, но смог найти что-нибудь, связанное с BiometricPrefecene.

Любая помощь будет высоко оценен.

0 ответов

Хотя это не идеальное решение, вы можете использовать PackageManager API, чтобы определить, есть ли на устройстве оборудование для аутентификации, например:

if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE))
{
}

Я создал вспомогательный класс следующим образом:

class BiometricAuthenticator
{
 public enum BiometricType
 {
  FINGERPRINT,
  FACE, 
  IRIS,
  NONE
 }

 public static boolean hasBiometricAuthenticator(Context context)
 {
    int biometry = BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED;
    if (VERSION.SDK_INT >= 30)
        biometry = BiometricManager.from(context).canAuthenticate(Authenticators.BIOMETRIC_STRONG | Authenticators.BIOMETRIC_WEAK);
    else
        biometry = BiometricManager.from(context).canAuthenticate();

    switch (biometry)
    {
        case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
        case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
        case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
             return (false);
        case BiometricManager.BIOMETRIC_SUCCESS:
             return true;
    }
    return (false);
 }

 /**
  * biometricType()
  *
  * returns type of biometry supported
  */
 public static BiometricType biometricType(Context context)
 {
    if (VERSION.SDK_INT < 23)
        return BiometricType.NONE;

    PackageManager packageManager = context.getPackageManager();

    // SDK 29 adds FACE and IRIS authentication
    if (VERSION.SDK_INT >= 29)
    {
        if (packageManager.hasSystemFeature(PackageManager.FEATURE_FACE))
            return BiometricType.FACE;
        if (packageManager.hasSystemFeature(PackageManager.FEATURE_IRIS))
            return BiometricType.IRIS;
        if (packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
            return BiometricType.FINGERPRINT;
        return BiometricType.NONE;
    }

    // SDK 23-28 offer FINGERPRINT only
    return (packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) ? BiometricType.FINGERPRINT : BiometricType.NONE);
 }
}

Это позволяет определить, присутствует ли биометрический аутентификатор (hasBiometricAuthenticator), и если да, верните тип аутентификатора как BiometricType перечисление.

Теоретически устройство может иметь несколько аутентификаторов, и biometricType() вернет FACE, IRIS, затем FINGERPRINT в указанном порядке на устройствах API30+.

Надеюсь, Google представит лучший API в будущем, но эти уловки, по крайней мере, помогут получить соответствующие подсказки в диалоговом окне.

На данный момент нет возможности узнать этот тип информации, в прошлом году была открыта проблема, чтобы запросить ее (https://issuetracker.google.com/issues/111315641). Поскольку Android попытался упростить разработчикам способ реализации аутентификации в своих приложениях, в реализации BiometricPrompt отсутствуют параметры (см. Документ Android для реализации BiometricPrompt).

В вашем случае вы можете просто изменить строку заголовка на "Биометрическая аутентификация" и так же с другими строками. Для примера см. Сообщения в блоге, указанные ниже.

Ваш код может выглядеть следующим образом. Но я также рекомендую вам использоватьstrings.xmlресурсный файл вместо жесткого кодирования ваших строк в коде. Например, в будущем вам могут потребоваться услуги переводчика.

biometricPrompt = new BiometricPrompt.Builder(context)
        .setTitle("Biometric Authentication")
        .setSubtitle("Login via biometrics")
        .setDescription("Use the Biometrics Sensor")
        .setNegativeButton("Cancel", context.getMainExecutor(),
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Log.d(TAG,"Cancelled");
                    }
                })
        .build();

В более широком смысле, необходимо оценить последствия для конфиденциальности, прежде чем команда API примет решение, должны ли разработчики знать биометрические предпочтения пользователя. На самом деле непонятно, зачем разработчику эта информация. Два сообщения в блоге были опубликованы, которые касаются предмета Strong против слабых биометрии и как их реализовать (блог один, блог два). Помимо этого различия (например, сильный против слабого), какие форм-факторы пользователь предпочитает или в конечном итоге использует, не кажется уместным.

В Android R был добавлен метод setAllowedAuthenticators.

public BiometricPrompt.Builder setAllowedAuthenticators (int authenticators)

Необязательно: указывает тип (ы) аутентификаторов, которые могут быть вызваны BiometricPrompt для аутентификации пользователя. Доступные типы аутентификаторов определены в Authenticators и могут быть объединены с помощью побитового ИЛИ. По умолчанию:

  • Аутентификаторы #BIOMETRIC_WEAK для не крипто-аутентификации, или
  • Аутентификаторы #BIOMETRIC_STRONG для криптографической аутентификации.

Если используется этот метод и во время вызова BiometricPrompt#authenticate(...) аутентификатор любого из указанных типов недоступен, аутентификация будет отменена и AuthenticationCallback#onAuthenticationError(int, CharSequence) будет вызван с соответствующей ошибкой. код.


Этот метод должен быть предпочтительнее setDeviceCredentialAllowed(boolean) и отменяет последний, если используются оба. Использование этого метода для включения аутентификации учетных данных устройства (с Authenticators#DEVICE_CREDENTIAL) заменит отрицательную кнопку в приглашении, что приведет к ошибке также при вызове setNegativeButton(java.lang.CharSequence, java.util.concurrent.Executor, android.content.DialogInterface.OnClickListener).


аутентификаторы

Битовое поле, представляющее все допустимые типы аутентификаторов, которые могут быть вызваны подсказкой. Значение равно 0 или комбинации BiometricManager.Authenticators.BIOMETRIC_STRONG, BiometricManager.Authenticators.BIOMETRIC_WEAK и BiometricManager.Authenticators.DEVICE_CREDENTIAL