12、错误码处理:BIOMETRIC_ERROR_HW_UNAVAILABLE、BIOMETRIC_ERROR_NONE_ENROLLED、BIOMETRIC_ERROR_NO_HARDWARE等
说实话,做Android人脸解锁最头疼的不是算法调优,而是那些冷不丁冒出来的错误码。我刚开始接触生物识别API时,就被这几个错误码折腾过好几个晚上。你想想看,用户满怀期待地点了“刷脸”,结果app直接弹个“无法识别”的提示,体验瞬间归零。
今天我们就来聊聊最常见的三个错误码。我会结合自己的踩坑经历,告诉你它们到底是什么意思,以及怎么优雅地处理。
BIOMETRIC_ERROR_NO_HARDWARE —— 硬件呢?
这个错误码的意思很直白:设备上压根没有生物识别硬件。嗯,说白了就是这台手机不支持人脸识别或指纹识别。
我在项目中遇到过一台很老的平板,系统版本倒是Android 9,但硬件上根本没有摄像头模组支持人脸识别。调用BiometricPrompt时直接返回了这个错误。当时我第一反应是“代码写错了”,查了半天才发现是硬件问题。
处理方式很简单:
// 检查硬件是否可用
if (!biometricManager.canAuthenticate(
BiometricManager.Authenticators.BIOMETRIC_STRONG)) {
int errorCode = biometricManager.getErrorCode();
if (errorCode == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) {
// 直接提示用户,不要尝试调用BiometricPrompt
showToast("此设备不支持人脸识别");
}
}
我个人习惯在应用启动时就做一次硬件检测,而不是等到用户点击“刷脸”按钮才去处理。这样能避免很多不必要的异常。
BIOMETRIC_ERROR_HW_UNAVAILABLE —— 硬件罢工了
这个错误码比上一个更“气人”。硬件明明存在,但就是不可用。什么情况?
最常见的原因是:硬件被占用。比如系统正在使用摄像头做其他事情(比如正在录像),或者人脸识别模组被其他应用锁住了。我记得有一次,用户反馈说“刷脸一直失败”,我远程调试发现,他后台挂了一个美颜相机app,摄像头一直被占着。
另一个常见场景是:系统服务崩溃或重启。Android的生物识别服务是一个系统级服务,偶尔会抽风。我曾在某款定制ROM上遇到过,每次锁屏再解锁后,第一次调用人脸识别必返回这个错误,第二次就正常了。嗯,这其实是系统bug,但我们作为应用层开发者,也得想办法兜底。
处理逻辑建议:
// 在BiometricPrompt的回调中处理
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE) {
// 不要立即弹窗,先记录次数
int retryCount = getRetryCount();
if (retryCount < 3) {
showToast("人脸识别暂时不可用,请稍后重试");
incrementRetryCount();
} else {
showDialog("多次尝试失败,建议重启手机或检查摄像头是否被占用");
resetRetryCount();
}
}
}
你想想看,用户遇到这个错误时,最需要的是“下一步该怎么做”,而不是冷冰冰的错误码。所以提示语一定要有引导性。
BIOMETRIC_ERROR_NONE_ENROLLED —— 没录入人脸
这个错误码可能是三个里面最“友好”的。它表示:硬件没问题,系统也正常,但用户没有录入任何生物特征(人脸或指纹)。
说白了,就是用户没在系统设置里录入人脸数据。我见过很多用户,下载了app后直接点“刷脸登录”,完全忘了自己根本没在手机设置里录过脸。这时候app如果直接崩溃或报错,体验就很糟糕。
正确的做法是:引导用户去系统设置页面录入人脸。Android提供了标准的Intent,可以直接跳转到生物识别录入界面。
if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_NONE_ENROLLED) {
// 弹出确认对话框
new AlertDialog.Builder(context)
.setTitle("需要录入人脸")
.setMessage("请先在系统设置中录入人脸信息")
.setPositiveButton("去设置", (dialog, which) -> {
// 跳转到系统录入页面
Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
BiometricManager.Authenticators.BIOMETRIC_STRONG);
startActivity(enrollIntent);
})
.setNegativeButton("取消", null)
.show();
}
这里要注意一点:Settings.ACTION_BIOMETRIC_ENROLL 是从Android 11才开始支持的。如果你的app需要兼容更低版本,可以用 Settings.ACTION_SECURITY_SETTINGS 跳转到安全设置页面,让用户手动找到“人脸录入”选项。虽然多了一步,但总比报错强。
三个错误码的对比总结
为了方便记忆,我整理了一个表格。你写代码时可以直接参考:
| 错误码 | 含义 | 是否可恢复 | 推荐处理方式 |
|---|---|---|---|
| BIOMETRIC_ERROR_NO_HARDWARE | 无硬件 | 不可恢复 | 提示设备不支持,禁用刷脸功能 |
| BIOMETRIC_ERROR_HW_UNAVAILABLE | 硬件暂时不可用 | 可恢复(通常) | 提示稍后重试,建议重启手机 |
| BIOMETRIC_ERROR_NONE_ENROLLED | 未录入生物特征 | 可恢复 | 引导用户去系统设置录入 |
知识体系:错误码处理的核心逻辑
下面这张图是我自己总结的。每次写生物识别功能时,我都会对照这个流程来设计错误处理:
从图中可以看到,三个错误码的处理路径完全不同。我个人建议把错误处理逻辑封装成一个工具类,这样在多个页面调用时不会重复写代码。嗯,封装的时候记得把“重试次数”和“是否已引导过”的状态也管理起来,避免重复弹窗。
最后说一句:错误码不是敌人,它们是系统在帮你“排雷”。你处理得越优雅,用户就越觉得你的app“很稳”。