11、认证回调详解:onAuthenticationError、onAuthenticationSucceeded、onAuthenticationFailed、onAuthenticationAcquired
说实话,刚开始接触 Android 生物识别时,我一度被这四个回调搞得有点晕。尤其是 onAuthenticationError 和 onAuthenticationFailed,名字长得像,触发时机却完全不同。后来踩了几次坑,才真正搞明白它们各自的分工。
这一节,咱们就把这四个回调掰开揉碎,一个一个讲清楚。
回调总览:谁负责什么?
先看一张图,帮你快速建立整体认知。
简单来说:Error 是出大事了,Failed 是没匹配上但还能再试,Succeeded 是成功了,Acquired 是告诉你「我在干活了」。
1. onAuthenticationError:不可恢复的错误
这个回调,说白了就是「认证流程彻底挂了」。一旦触发,系统会终止本次认证,你不能再继续用同一个 BiometricPrompt 实例去重试。
触发场景
- 用户连续多次人脸识别失败,系统锁定生物识别
- 传感器硬件故障(比如摄像头被占用)
- 用户主动取消(按下返回键或取消按钮)
- 系统安全策略限制(比如设备处于锁屏状态过久)
错误码一览
| 错误码 | 含义 | 我的建议 |
|---|---|---|
| BIOMETRIC_ERROR_HW_UNAVAILABLE | 硬件不可用 | 提示用户稍后再试 |
| BIOMETRIC_ERROR_NO_BIOMETRICS | 未录入生物信息 | 引导用户去设置里录入 |
| BIOMETRIC_ERROR_LOCKOUT | 尝试次数过多,临时锁定 | 等待一段时间再试 |
| BIOMETRIC_ERROR_LOCKOUT_PERMANENT | 永久锁定,需用密码解锁 | 必须走备用验证方式 |
| BIOMETRIC_ERROR_CANCELED | 用户取消 | 正常处理,无需特殊提示 |
重点提醒:收到 BIOMETRIC_ERROR_LOCKOUT_PERMANENT 时,千万别再弹生物识别对话框了。我曾经见过一个 App,锁死后还在不停重试,结果用户直接给了一星差评。
代码示例
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
// 我个人习惯先判断错误码,再决定怎么处理
switch (errorCode) {
case BiometricPrompt.BIOMETRIC_ERROR_CANCELED:
// 用户主动取消,啥也不用干
break;
case BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT:
// 临时锁定,提示用户稍后重试
showToast("尝试次数过多,请30秒后再试");
break;
case BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
// 永久锁定,必须走备用验证
showToast("请使用密码验证");
navigateToPasswordScreen();
break;
default:
// 其他错误,统一提示
showToast("认证失败:" + errString);
break;
}
}
2. onAuthenticationSucceeded:认证成功
这是咱们最想看到的回调。用户人脸匹配成功,系统返回一个 BiometricPrompt.AuthenticationResult 对象。
你可能会问:这个结果对象里有什么?
- getAuthenticationType():返回使用的认证方式,比如
BIOMETRIC_STRONG或BIOMETRIC_WEAK - getCryptoObject():如果你传入了加密对象,这里可以取回来
一个小技巧:如果你只是做简单的登录验证,不需要加密操作,那 AuthenticationResult 基本用不上。但如果你在做支付或签名,记得从结果里取出 CryptoObject 进行后续操作。
@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
// 认证成功,放行用户
int authType = result.getAuthenticationType();
if (authType == BiometricPrompt.BIOMETRIC_STRONG) {
// 强生物识别,安全性高
grantAccess();
} else {
// 弱生物识别,可以加个二次确认
showConfirmDialog();
}
}
3. onAuthenticationFailed:匹配失败,但还能重试
这个回调特别容易和 onAuthenticationError 搞混。我刚开始学的时候也犯过这个错。
区别在哪?
onAuthenticationFailed:人脸不匹配,但系统还允许你继续尝试。对话框不会关闭。onAuthenticationError:出大事了,对话框关闭,认证终止。
说白了,onAuthenticationFailed 就是「没对上焦,再来一次」。系统会继续采集人脸数据,你只需要提示用户调整姿势或光线。
注意:不要在这个回调里调用 dismiss() 关闭对话框!我见过有人这么写,结果用户每次失败对话框就闪一下,体验极差。
@Override
public void onAuthenticationFailed() {
// 提示用户调整姿势
showToast("人脸不匹配,请调整姿势或光线");
// 不要关闭对话框,系统会自动继续尝试
}
4. onAuthenticationAcquired:采集过程中的状态信息
这个回调比较特殊。它不表示成功或失败,而是告诉你「系统正在采集人脸数据,当前采集质量如何」。
它携带一个 acquireInfo 参数,常见值有:
| acquireInfo | 含义 |
|---|---|
| BIOMETRIC_ACQUIRED_GOOD | 采集质量良好 |
| BIOMETRIC_ACQUIRED_INSUFFICIENT | 采集质量差,需要调整 |
| BIOMETRIC_ACQUIRED_TOO_FAST | 移动太快,没捕捉到 |
| BIOMETRIC_ACQUIRED_TOO_SLOW | 保持姿势时间不够 |
嗯,这里要注意:这个回调在 Android 9 及以下版本可能不会被调用。所以别把核心逻辑写在这里。
@Override
public void onAuthenticationAcquired(int acquireInfo) {
switch (acquireInfo) {
case BiometricPrompt.BIOMETRIC_ACQUIRED_GOOD:
// 采集质量好,啥也不用做
break;
case BiometricPrompt.BIOMETRIC_ACQUIRED_INSUFFICIENT:
showToast("请靠近一点,光线充足些");
break;
case BiometricPrompt.BIOMETRIC_ACQUIRED_TOO_FAST:
showToast("请保持姿势,不要移动太快");
break;
}
}
实战经验总结
最后,分享几个我在项目中踩过的坑:
- 回调顺序别搞反:
onAuthenticationAcquired会先于onAuthenticationSucceeded或onAuthenticationFailed触发。别在Acquired里做成功判断。 - Failed 回调可能连续触发:用户连续失败时,系统会多次调用
onAuthenticationFailed。你不需要做节流,系统自己会处理。 - Error 回调后记得清理状态:一旦收到
onAuthenticationError,之前的BiometricPrompt实例就不能再用了。需要重新创建。 - 我曾经遇到过一个问题:在
onAuthenticationSucceeded里直接跳转页面,结果动画还没播完就崩溃了。后来发现是回调线程和 UI 线程的问题。建议用Handler或runOnUiThread做页面跳转。
一句话总结:Error 是终结,Failed 是重试,Succeeded 是放行,Acquired 是状态。把这四个回调理解透,生物识别认证流程你就掌握了八成。