确定是否存在生物识别硬件且用户已在Android P上注册生物识别

sir*_*ius 33 android biometrics android-9.0-pie

我被要求根据生物识别硬件的存在显示某些UI元素.对于Android 23-27我使用FingerprintManager#isHardwareDetected()FingerprintManager#hasEnrolledFingerprints().这两个都在Android 28中被弃用.

我明白,我可以用得到这个信息BiometricPrompt#authenticate(...),并在接受BiometricPrompt#BIOMETRIC_ERROR_HW_NOT_PRESENTBiometricPrompt#BIOMETRIC_ERROR_NO_BIOMETRICSBiometricPrompt.AuthenticationCallback#onAuthenticationError(int errorCode, ...)方法.但这会导致BiometricPrompt在支持设备上显示,这是不希望的.使用它CancellationSignal似乎也不是解决方案,因为我不知道何时取消提示.

有没有办法检测生物识别硬件的存在和用户注册?

sir*_*ius 14

Google终于用Android Q解决了这个问题

所述android.hardware.biometrics.BiometricManager#canAuthenticate()方法可以用于确定是否可以使用生物测定。

该方法可用于确定是否存在生物识别硬件以及是否已注册用户。

如果用户没有注册,则返回BIOMETRIC_ERROR_NONE_ENROLLED;如果当前不支持/启用,则返回BIOMETRIC_ERROR_HW_UNAVAILABLE。如果当前可以使用生物特征(已注册并可用),则返回BIOMETRIC_SUCCESS。

希望将其添加到androidx.biometric:biometric库中,以便可以在所有设备上使用。

在此之前,@ algrid的解决方案可以确定生物特征识别注册。

并且以下内容可用于确定是否存在指纹读取器。

Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
            context.packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
Run Code Online (Sandbox Code Playgroud)

  • 这仅适用于 Android 10,对于 6 到 9,当面部、虹膜等注册时(指纹除外),它将返回 HW_UNAVAILABLE (2认同)

alg*_*rid 6

可悲的是,谷歌将相关问题的状态更改为“不会解决(预期行为)”无法解决此问题。我现在更喜欢使用旧的API。

但是对于那些想使用较新API的人来说,有一种骇人/丑陋的方式来获得hasEnrolledFingerprints()模拟信号(该代码适用于API23 +):

public boolean isBiometryAvailable() {
    KeyStore keyStore;
    try {
        keyStore = KeyStore.getInstance("AndroidKeyStore");
    } catch (Exception e) {
        return false;
    }

    KeyGenerator keyGenerator;
    try {
        keyGenerator = KeyGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
    } catch (NoSuchAlgorithmException |
            NoSuchProviderException e) {
        return false;
    }

    if (keyGenerator == null || keyStore == null) {
        return false;
    }

    try {
        keyStore.load(null);
        keyGenerator.init(new
                KeyGenParameterSpec.Builder("dummy_key",
                KeyProperties.PURPOSE_ENCRYPT |
                        KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .build());
    } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
            | CertificateException | IOException e) {
        return false;
    }
    return true;

}
Run Code Online (Sandbox Code Playgroud)

这基于以下Android keystore docs语句:

  • 用户身份验证授权与一个密钥关联的特定加密操作。在这种模式下,涉及该键的每个操作必须由用户单独授权。当前,这种授权的唯一方法是指纹认证:FingerprintManager.authenticate。只有注册了至少一个指纹后,才能生成或导入此类密钥(请参阅FingerprintManager.hasEnrolledFingerprints)。一旦注册了新指纹或未注册所有指纹,这些密钥将永久失效。

请参阅https://developer.android.com/training/articles/keystore中的“要求使用密钥进行用户身份验证”部分


mly*_*yko 6

AndroidX生物识别库开始提供版本1.0.0-beta01androidx.biometric:biometric:1.0.0-beta01)中的此类信息

BiometricManager.from(context).canAuthenticate()
Run Code Online (Sandbox Code Playgroud)

哪一个返回

  • BIOMETRIC_SUCCESS
  • BIOMETRIC_ERROR_HW_UNAVAILABLE
  • BIOMETRIC_ERROR_NONE_ENROLLED
  • BIOMETRIC_ERROR_NO_HARDWARE

请参阅更改日志: https : //developer.android.com/jetpack/androidx/releases/biometric#1.0.0-beta01


mar*_*eno 5

我为 Kotlin 写了这个方法:

fun checkForBiometrics() : Boolean{
    Log.d(TAG, "checkForBiometrics started")
    var canAuthenticate = true
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (Build.VERSION.SDK_INT < 29) {
            val keyguardManager : KeyguardManager = applicationContext.getSystemService(KEYGUARD_SERVICE) as KeyguardManager
            val packageManager : PackageManager   = applicationContext.packageManager
            if(!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
                Log.w(TAG, "checkForBiometrics, Fingerprint Sensor not supported")
                canAuthenticate = false
            }
            if (!keyguardManager.isKeyguardSecure) {
                Log.w(TAG, "checkForBiometrics, Lock screen security not enabled in Settings")
                canAuthenticate = false
            }
        } else {
            val biometricManager : BiometricManager = this.getSystemService(BiometricManager::class.java)
            if(biometricManager.canAuthenticate() != BiometricManager.BIOMETRIC_SUCCESS){
                Log.w(TAG, "checkForBiometrics, biometrics not supported")
                canAuthenticate = false
            }
        }
    }else{
        canAuthenticate = false
    }
    Log.d(TAG, "checkForBiometrics ended, canAuthenticate=$canAuthenticate ")
    return canAuthenticate
}
Run Code Online (Sandbox Code Playgroud)

此外,您必须在您的应用程序 gradle 文件上实现作为依赖项:

implementation 'androidx.biometric:biometric:1.0.0-alpha04'
Run Code Online (Sandbox Code Playgroud)

并使用最新的构建工具:

compileSdkVersion 29
buildToolsVersion "29.0.1"
Run Code Online (Sandbox Code Playgroud)

  • 我认为你必须在你的 gradle 应用程序文件上使用:compileSdkVersion 29和buildToolsVersion“29.0.1”。 (2认同)