6、BiometricManager状态检查:canAuthenticate()方法、BiometricManager响应码解析、设备兼容性判断
好,咱们接着聊。上一章我们把 BiometricPrompt 的调用流程走通了,但有个关键问题:你怎么知道当前手机支不支持人脸识别?
总不能直接弹个对话框,结果发现设备压根没硬件,那用户体验就太糟糕了。我个人习惯是,在调用任何生物识别 API 之前,先做一次「体检」。这个体检工具就是 BiometricManager。
6.1 BiometricManager 是什么?
说白了,BiometricManager 是 Android 提供的一个系统服务,专门用来查询设备的生物识别能力。它不负责认证,只负责告诉你:
- 设备有没有指纹/人脸/虹膜硬件
- 硬件是否可用(有没有被损坏)
- 用户有没有录入生物特征
- 当前应用有没有权限使用
你可以把它理解成「安检员」。在乘客(用户)进入闸机(认证)之前,先检查一下票(生物特征)有没有买、闸机有没有坏。
6.2 canAuthenticate() 方法
核心方法就一个:
BiometricManager manager = BiometricManager.from(context);
int result = manager.canAuthenticate();
返回的是一个整型响应码。我刚开始接触时,以为返回 true/false 就行了,结果 Google 设计了一个枚举值。为什么?因为失败的原因太多了,一个布尔值根本不够用。
6.3 响应码全解析
咱们直接看表,这是我在项目中反复对照的:
| 响应码 | 常量名 | 含义 | 处理建议 |
|---|---|---|---|
| 0 | BIOMETRIC_SUCCESS | 一切正常,可以认证 | 直接调用 BiometricPrompt |
| 1 | BIOMETRIC_ERROR_HW_UNAVAILABLE | 硬件不可用(被占用或损坏) | 提示用户稍后再试 |
| 2 | BIOMETRIC_ERROR_NONE_ENROLLED | 用户没有录入任何生物特征 | 引导用户去设置页录入 |
| 3 | BIOMETRIC_ERROR_NO_HARDWARE | 设备没有生物识别硬件 | 降级到密码/PIN 认证 |
| 4 | BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED | 安全补丁未更新 | 提示用户更新系统 |
| 5 | BIOMETRIC_ERROR_UNSUPPORTED | 当前 API 版本不支持 | 检查 minSdkVersion |
| 6 | BIOMETRIC_ERROR_STATUS | 底层 HAL 返回了错误状态 | 记录日志,联系厂商 |
BIOMETRIC_SUCCESS(0)—— 绿灯,直接走BIOMETRIC_ERROR_NONE_ENROLLED(2)—— 最常见的问题,用户没录脸BIOMETRIC_ERROR_NO_HARDWARE(3)—— 老设备或平板常见
6.4 设备兼容性判断
嗯,这里要注意。不是所有 Android 手机都支持人脸识别。我遇到过一台 2018 年的低端机,系统是 Android 10,但硬件上根本没有前置摄像头的人脸识别模块。调用 canAuthenticate() 直接返回 BIOMETRIC_ERROR_NO_HARDWARE。
所以兼容性判断的逻辑应该是:
int result = manager.canAuthenticate();
if (result == BiometricManager.BIOMETRIC_SUCCESS) {
// 设备支持,用户已录入,可以认证
showBiometricPrompt();
} else if (result == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
// 设备支持,但用户没录入
showEnrollDialog();
} else {
// 设备不支持或硬件不可用
fallbackToPassword();
}
我曾经踩过一个坑:在 BIOMETRIC_ERROR_NONE_ENROLLED 的情况下,直接弹 Toast 说「请去设置页录入指纹/人脸」。结果用户反馈说找不到入口。后来我加了一个 Intent 跳转到系统设置页:
Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
BiometricManager.Authenticators.BIOMETRIC_STRONG);
startActivity(enrollIntent);
你想想看,用户其实不是不想用,是根本不知道去哪录。这个跳转能大幅提升录入率。
6.5 知识体系图
我把整个检查流程画了一张图,方便你理解:
6.6 实战中的避坑指南
最后分享几个我踩过的坑:
虽然这个方法本身很快,但某些厂商的 ROM 实现有 BUG,可能会卡住主线程。我建议在 IO 线程或协程里调用。
Android 11 之后,canAuthenticate() 可以传入 Authenticators 参数。如果你只想要人脸(强生物识别),可以这样写:
int result = manager.canAuthenticate(
BiometricManager.Authenticators.BIOMETRIC_STRONG
);
这样就不会把「面部解锁(弱)」算作可用。
我记得第一次在模拟器上调试,怎么调都是 BIOMETRIC_ERROR_NO_HARDWARE。后来才发现,Android 模拟器默认没有生物识别硬件。你需要手动在 AVD 设置里开启「Fingerprint」或「Face」支持。
好了,关于 BiometricManager 的状态检查就聊到这。记住一个原则:先检查,后认证。这能帮你避免 90% 的运行时异常。
canAuthenticate() 返回 0 才能调 BiometricPrompt,其他情况要么引导用户录入,要么降级方案。
公众号:蓝海资料掘金营,微信deep3321