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

问题描述 投票:21回答:3

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

我知道我可以通过使用BiometricPrompt#authenticate(...)并在BiometricPrompt#BIOMETRIC_ERROR_HW_NOT_PRESENT方法中接收BiometricPrompt#BIOMETRIC_ERROR_NO_BIOMETRICSBiometricPrompt.AuthenticationCallback#onAuthenticationError(int errorCode, ...)来获取此信息。但这会导致BiometricPrompt显示在支持设备上,这是不可取的。使用CancellationSignal似乎也不是解决方案,因为我不知道何时取消提示。

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

android biometrics android-9.0-pie
3个回答
9
投票

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

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

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

如果用户没有任何已注册,则返回BIOMETRIC_ERROR_NONE_ENROLLED;如果当前未支持/启用BIOMETRIC_ERROR_HW_UNAVAILABLE,则返回BIOMETRIC_ERROR_HW_UNAVAILABLE。如果当前可以使用生物特征识别(已登记且可用),则返回BIOMETRIC_SUCCESS。

希望这被添加到androidx.biometric:biometric库中,因此它可以在所有设备上使用。

在此之前,@ algrid的解决方案致力于确定生物识别登记。

如果存在指纹读取器,则可以使用以下内容来确定。

Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
            context.packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)

5
投票

遗憾的是,谷歌不会解决这个问题,将相关问题的状态改为“不会修复(预期行为)”。我现在更喜欢使用旧的弃用API。

但对于那些想要使用更新的API的人来说,有一种hacky /丑陋的方式来获得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;

}

这基于以下Android密钥库docs语句:

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

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


0
投票

该方法 - 在使用程序包管理器验证设备上是否可以使用指纹身份验证之前,检查用户是否为应用程序启用了生物识别身份验证权限。甚至它会检查用户是否注册。

实现'androidx.biometric:biometric:1.0.0-alpha03'

private Boolean checkBiometricSupport() {

    KeyguardManager keyguardManager =
            (KeyguardManager) getSystemService(KEYGUARD_SERVICE);

    PackageManager packageManager = this.getPackageManager();

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        notifyUser("This Android version does not support fingerprint authentication.");
        return false;
    }

    if(!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
    {
        notifyUser("Fingerprint Sensor not supported");
        return false;
    }

    if (!keyguardManager.isKeyguardSecure()) {
        notifyUser("Lock screen security not enabled in Settings");

        return false;
    }

    if (ActivityCompat.checkSelfPermission(this,
            Manifest.permission.USE_BIOMETRIC) !=
            PackageManager.PERMISSION_GRANTED) {
        notifyUser("Fingerprint authentication permission not enabled");

        return false;
    }

    return true;
}
© www.soinside.com 2019 - 2024. All rights reserved.