我被要求根据生物识别硬件的存在显示某些UI元素。对于Android 23-27,我使用FingerprintManager#isHardwareDetected()
和FingerprintManager#hasEnrolledFingerprints()
。这两个都在Android 28中被弃用。
我知道我可以通过使用BiometricPrompt#authenticate(...)
并在BiometricPrompt#BIOMETRIC_ERROR_HW_NOT_PRESENT
方法中接收BiometricPrompt#BIOMETRIC_ERROR_NO_BIOMETRICS
或BiometricPrompt.AuthenticationCallback#onAuthenticationError(int errorCode, ...)
来获取此信息。但这会导致BiometricPrompt
显示在支持设备上,这是不可取的。使用CancellationSignal
似乎也不是解决方案,因为我不知道何时取消提示。
有没有办法检测生物识别硬件的存在和用户注册?
谷歌终于用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)
遗憾的是,谷歌不会解决这个问题,将相关问题的状态改为“不会修复(预期行为)”。我现在更喜欢使用旧的弃用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中的“要求密钥使用的用户身份验证”部分
该方法 - 在使用程序包管理器验证设备上是否可以使用指纹身份验证之前,检查用户是否为应用程序启用了生物识别身份验证权限。甚至它会检查用户是否注册。
实现'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;
}