5、认证回调详解:onAuthenticationSucceeded、onAuthenticationFailed、onAuthenticationError、onAuthenticationHelp、回调线程与UI更新
好,咱们接着聊。上一章我们把 BiometricPrompt 的构建和启动讲清楚了,但说实话,那只是搭了个台子。真正唱戏的,是这几个回调方法。你想想看,用户把手指按上去,系统怎么告诉你结果?就是靠这些回调。
我个人习惯把回调分成两类:成功类和失败/异常类。咱们一个一个过,每个我都会结合项目里的坑来讲。
5.1 onAuthenticationSucceeded —— 最让人开心的回调
这个方法被调用,意味着指纹匹配成功,用户身份验证通过。代码很简单:
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
// 用户验证成功
showMessage("指纹识别成功");
// 解锁应用或执行敏感操作
unlockApp();
}
这里有个细节,AuthenticationResult 对象里其实藏着一些信息。比如 result.getAuthenticationType(),它可以告诉你用户是用指纹、人脸还是虹膜验证的。我在项目中遇到过需要区分验证方式的场景——某些金融类 App 对指纹和人脸的信任等级不一样,这时候这个返回值就派上用场了。
5.2 onAuthenticationFailed —— 最常见的"不匹配"
这个回调在指纹匹配失败时触发。注意,它和 onAuthenticationError 有本质区别:Failed 只是匹配不成功,系统还在继续监听;Error 是系统出问题了,监听已经停止。
@Override
public void onAuthenticationFailed() {
// 指纹不匹配,但可以继续尝试
showMessage("指纹不匹配,请重试");
// 可以在这里做震动反馈
performHapticFeedback();
}
嗯,这里要注意。onAuthenticationFailed 不会自动停止指纹传感器。用户连续按 5 次失败后,系统才会触发 onAuthenticationError,并锁定传感器一段时间。我曾经在项目里踩过这个坑——用户连续失败后,我还在界面上显示"请重试",结果传感器已经锁了,用户怎么按都没反应。后来我加了个计数器,连续失败 3 次就提示用户用备用方式登录。
5.3 onAuthenticationError —— 出大事了
这个回调表示发生了不可恢复的错误,指纹传感器已经停止工作。常见的错误码有:
| 错误码 | 含义 | 常见原因 |
|---|---|---|
| BIOMETRIC_ERROR_HW_UNAVAILABLE | 硬件不可用 | 传感器被占用或损坏 |
| BIOMETRIC_ERROR_NO_BIOMETRICS | 未录入指纹 | 用户没在设置里录指纹 |
| BIOMETRIC_ERROR_LOCKOUT | 锁定 | 连续失败次数过多 |
| BIOMETRIC_ERROR_USER_CANCELED | 用户取消 | 用户点了取消按钮 |
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
// 传感器已停止,需要处理错误
switch (errorCode) {
case BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT:
showMessage("指纹已锁定,请使用密码登录");
showPasswordLogin();
break;
case BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED:
// 用户主动取消,不做特殊处理
break;
default:
showMessage("指纹识别出错: " + errString);
break;
}
}
我个人习惯在 onAuthenticationError 里做两件事:一是给用户明确的提示,二是提供备用验证方案。你想想看,用户指纹被锁了,你总不能让他干等着吧?
5.4 onAuthenticationHelp —— 容易被忽略的"小提示"
这个回调很有意思。它表示指纹传感器还在工作,但遇到了一些小问题,需要用户调整。比如手指移动太快、传感器有污渍等。
@Override
public void onAuthenticationHelp(int helpCode, @NonNull CharSequence helpString) {
// 传感器还在工作,但需要用户配合
showMessage(helpString); // 直接显示系统提供的提示文字
// 比如:"手指移动太快"、"请覆盖整个传感器"
}
说实话,很多开发者直接忽略这个回调。但我建议你好好利用它。我在项目中遇到过用户反复失败的情况,后来发现是传感器上有汗渍。系统通过 onAuthenticationHelp 提示了"传感器不干净",但我们的 UI 没显示出来,用户就一直擦手指,越擦越油。后来我把 helpString 直接显示在界面上,问题就解决了。
5.5 回调线程与UI更新 —— 最容易出bug的地方
好,这是个大坑。所有回调方法默认在什么线程执行?答案是:取决于你创建 BiometricPrompt 时传入的 Handler。
如果你没传 Handler,回调会在主线程执行。如果你传了 Handler,回调就在那个 Handler 绑定的线程执行。看代码:
// 方式一:不传 Handler,回调在主线程
BiometricPrompt prompt = new BiometricPrompt(this, executor, callback);
// 方式二:传 Handler,回调在指定线程
Handler backgroundHandler = new Handler(backgroundThread.getLooper());
BiometricPrompt prompt = new BiometricPrompt(this, backgroundHandler, callback);
我个人强烈建议:永远在主线程处理回调。为什么?因为回调里你大概率要更新 UI——显示成功/失败提示、更新指纹图标、跳转页面等。这些操作必须在主线程做。
如果你非要在后台线程处理回调,那更新 UI 时记得切回主线程:
@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
// 当前在后台线程
runOnUiThread(() -> {
// 更新 UI
showSuccessAnimation();
});
}
我曾经在项目里犯过这个错——回调里直接更新 TextView,结果在 Android 7.0 上偶尔崩溃,因为某些厂商的 BiometricPrompt 实现把回调抛到了子线程。后来我统一加了个 runOnUiThread,世界清净了。
5.6 知识体系总览
说了这么多,咱们用一张图把回调的完整流程串起来:
从图上可以看得很清楚:用户触摸后,系统开始匹配。匹配成功走绿色分支,匹配失败走红色分支,需要用户调整走黄色分支。只有 onAuthenticationError 是终点——它表示整个认证流程结束了。
好了,回调这块就讲这么多。记住一句话:成功回调要处理结果,失败回调要引导用户,错误回调要提供备选方案,帮助回调要显示提示文字。线程问题统一用主线程处理,别给自己挖坑。
公众号:蓝海资料掘金营,微信deep3321