4、BiometricPrompt 基础使用:创建实例、设置回调、启动认证、处理结果
好,咱们今天来聊聊 BiometricPrompt 最核心的用法。
说白了,就是四步走:创建实例 → 设置回调 → 启动认证 → 处理结果。
这四步走顺了,指纹认证的基本功就算拿下了。我在项目里见过不少新手,一上来就急着调 authenticate(),结果回调没配好,认证失败了都不知道为啥。嗯,咱们一步步来。
4.1 创建 BiometricPrompt 实例
创建实例其实很简单,就一行代码。但这里有个关键点——你必须绑定一个主线程的 Looper。为什么?因为认证回调需要跑在主线程,你才能安心更新 UI。
// 我个人习惯用 this 作为 context,前提是你在 Activity 里
BiometricPrompt biometricPrompt = new BiometricPrompt(
this, // FragmentActivity 或 Fragment
Executors.newSingleThreadExecutor(), // 后台线程,用于处理认证操作
new BiometricPrompt.AuthenticationCallback() { ... } // 回调
);
等等,这里有个坑。你可能会想:「我直接用 MainExecutor 不就行了?」
嗯,是可以。但我建议你单独开一个后台线程。为什么呢?因为指纹认证的底层操作(比如跟指纹硬件通信)可能会阻塞主线程。我在项目中遇到过,用 MainExecutor 时,快速连续调用认证,界面会卡一下。换成后台线程后,流畅多了。
ContextCompat.getMainExecutor(this) 获取主线程执行器。但如果你要做耗时操作,还是自己建个线程池吧。
4.2 设置认证回调
回调是 BiometricPrompt 的灵魂。你想想看,用户把手指放上去,系统怎么告诉你结果?全靠回调。
回调主要有三个方法,我按重要程度排个序:
| 回调方法 | 触发时机 | 我常用的处理 |
|---|---|---|
onAuthenticationSucceeded() |
认证成功 | 跳转页面、解锁功能、记录日志 |
onAuthenticationError() |
发生不可恢复的错误(如指纹传感器被锁定) | 提示用户、关闭认证、记录错误码 |
onAuthenticationFailed() |
指纹匹配失败(可重试) | 提示「指纹不匹配,请重试」 |
这里有个细节,onAuthenticationFailed() 和 onAuthenticationError() 的区别:
- Failed:只是这次指纹没对上,你可以继续让用户试。
- Error:系统告诉你「别试了,再试也没用」。比如连续失败 5 次后,传感器会暂时锁定。
我曾经踩过一个坑:在 onAuthenticationError() 里直接弹 Toast 说「认证失败」,结果用户一脸懵——明明还能再试啊。后来我改成根据错误码区分提示,用户体验好多了。
new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
// 认证成功,解锁!
unlockApp();
}
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
// 不可恢复的错误,提示用户
showErrorDialog("认证出错:" + errString);
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
// 指纹不匹配,可重试
showToast("指纹不匹配,请重试");
}
};
4.3 启动指纹认证
实例有了,回调配好了,接下来就是启动认证。这一步最容易被忽略的是——你要先检查有没有指纹硬件、有没有录入指纹。
我习惯的做法是:
// 先检查硬件和指纹
BiometricManager biometricManager = BiometricManager.from(this);
switch (biometricManager.canAuthenticate()) {
case BiometricManager.BIOMETRIC_SUCCESS:
// 可以认证,启动!
startBiometricAuth();
break;
case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
// 没有指纹硬件
showToast("设备不支持指纹");
break;
case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
// 没有录入指纹
showToast("请先录入指纹");
break;
default:
// 其他错误
showToast("指纹不可用");
}
检查通过后,启动认证的代码其实就一行:
biometricPrompt.authenticate(
new BiometricPrompt.PromptInfo.Builder()
.setTitle("指纹验证")
.setSubtitle("请将手指放在传感器上")
.setDescription("使用指纹解锁应用")
.setNegativeButtonText("取消")
.build()
);
这里有个小细节:setNegativeButtonText 是必须的。为什么?因为系统需要给用户一个「取消」的入口。如果你不设,会直接崩溃。嗯,我当年就因为这个被测试妹子提过 bug……
authenticate() 方法必须在主线程调用。如果你在后台线程调,会抛出 IllegalStateException。别问我怎么知道的……
4.4 处理认证结果
认证结果的处理,说白了就是回调里的那几件事。但我发现很多人只处理成功和失败,忽略了取消操作和重试逻辑。
举个例子:用户点「取消」后,系统会回调 onAuthenticationError(),错误码是 BiometricPrompt.ERROR_NEGATIVE_BUTTON。这时候你应该做什么?
- 不要弹错误提示(用户主动取消的,不是错误)
- 关闭认证界面
- 记录用户取消了认证
再比如重试逻辑。用户第一次指纹没对上,你提示「请重试」。但第二次又没对上呢?第三次呢?
我建议你设置一个最大重试次数,比如 3 次。超过后自动调用 biometricPrompt.cancelAuthentication(),然后提示用户「尝试次数过多,请稍后再试」。
private int retryCount = 0;
private static final int MAX_RETRY = 3;
@Override
public void onAuthenticationFailed() {
retryCount++;
if (retryCount >= MAX_RETRY) {
biometricPrompt.cancelAuthentication();
showToast("尝试次数过多,请稍后再试");
} else {
showToast("指纹不匹配,请重试(" + (MAX_RETRY - retryCount) + "次机会)");
}
}
这个重试逻辑,我在项目里用过很多次。用户反馈说「比系统默认的提示友好多了」。
4.5 核心流程一览
说了这么多,咱们用一张图把整个流程串起来。你一看就明白了。
这张图把整个流程串起来了。你从「创建实例」开始,一路走到「处理结果」。注意看「认证失败」那条虚线——它指向「认证错误」,表示失败后可以重试。但如果是「认证错误」,那就直接结束了。
4.6 避坑指南
最后,我把自己踩过的坑总结一下,你遇到了直接跳过:
- 不要在 onAuthenticationFailed() 里弹 Dialog:用户可能连续失败多次,弹 Dialog 会打断操作。用 Toast 或 Snackbar 就好。
- 记得在 onPause() 里取消认证:如果用户按 Home 键退出了,认证还在进行,回来时会出问题。我习惯在 onPause() 里调
biometricPrompt.cancelAuthentication()。 - 错误码要处理全:比如
BIOMETRIC_ERROR_LOCKOUT(锁定 30 秒)和BIOMETRIC_ERROR_LOCKOUT_PERMANENT(永久锁定,需要用户去设置里重新录入)。处理方式完全不同。
好了,这一章的内容就到这儿。你先把代码跑起来,感受一下指纹认证的完整流程。下一章咱们聊聊更高级的——如何自定义认证弹窗的样式。