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



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

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

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

谷歌终于用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)

AndroidX生物识别库从版本1.0.0-beta01开始提供此类信息(androidx.biometric:biometric:1.0.0-beta01

BiometricManager.from(context).canAuthenticate()

返回以下之一

  • 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

可悲的是,谷歌不会解决这个问题,将相关问题的状态更改为"无法修复(预期行为("。我现在更喜欢使用旧的已弃用的 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;
}

这是基于以下 Android 密钥库文档声明:

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

请参阅此处的"密钥使用需要用户身份验证"部分 https://developer.android.com/training/articles/keystore

我为 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
}

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

implementation 'androidx.biometric:biometric:1.0.0-alpha04'

还可以使用最新的构建工具:

compileSdkVersion 29
buildToolsVersion "29.0.1"

在我的生物识别技术中,我使用了这些检查和其他一些检查,以确保设备有能力并且启用了指纹。在 Kotlin 中,我创建了一个 Object 类并将其称为实用程序。

object BiometricUtilities {
fun isBiometricPromptEnabled(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
}
fun isSdkVersionSupported(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
}
fun isHardwareSupported(context: Context): Boolean {
val fingerprintManager = FingerprintManagerCompat.from(context)
return fingerprintManager.isHardwareDetected
}
fun isFingerprintAvailable(context: Context): Boolean {
val fingerprintManager = FingerprintManagerCompat.from(context)
return fingerprintManager.hasEnrolledFingerprints()
}
}

然后在我的 bioManager 类中,我将条件语句放在一个名为 authenticate 的函数下,该函数实现了 BiometricCallback

fun authenticate(biometricCallback: BiometricCallback) {
if (!BiometricUtilities.isHardwareSupported(context)) {
biometricCallback.onBiometricAuthenticationNotSupported()
return
}
if (!BiometricUtilities.isFingerprintAvailable(context)) {
val intent = Intent(Settings.ACTION_SECURITY_SETTINGS)
biometricCallback.onBiometricAuthenticationNotAvailable()
return
}
displayBiometricDialog(biometricCallback)
}

通过这种方式,您可以检查设备上硬件的可用性和指纹的存在,并让操作系统帮助您显示提示与否

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

实现"安卓X.生物识别:生物识别: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;
}

FingerprintManagerCompat.from(this).isHardwareDetectedandroidx.core.hardware.fingerprint有可用的类方法。

对于那些不想等待支持库发布的人,你可以像这样使用夜间构建

repositories {
maven {
url "https://ci.android.com/builds/submitted/5795878/androidx_snapshot/latest/repository/"
}
}
implementation group: 'androidx.biometric', name: 'biometric', version: '1.0.0-SNAPSHOT'

从这里获取构建版本

https://ci.android.com/builds/branches/aosp-androidx-master-dev/

分支aosp-androidx-master-dev

显示来自androidx-snapshot的最新版本

最新更新