2、Android Biometric API 演进:从 FingerprintManager 到 BiometricPrompt

说起 Android 上的指纹识别,我最早接触是在 Android 6.0 时代。那时候 Google 刚推出官方的指纹 API,大家都很兴奋——终于不用依赖厂商私有的 SDK 了。但说实话,那个年代的体验真的挺粗糙的。后来到了 Android 9.0,Google 终于推出了统一的 BiometricPrompt,算是把生物识别这件事真正做「正规」了。再到 Android 10+,又加入了强生物识别的概念,安全性上了一个台阶。

这一章,我就带你捋一遍这个演进过程。你想想看,如果你现在要做一个支持指纹识别的 App,到底该用哪个 API?怎么兼容老设备?嗯,这就是我们要聊的核心。

一句话总结:Android 6.0 的 FingerprintManager 是「开荒者」,Android 9.0 的 BiometricPrompt 是「统一者」,Android 10+ 的强生物识别是「安全升级」。
Android 生物识别 API 演进时间线 6.0 FingerprintManager 2015年 ⚠ 已废弃 9.0 BiometricPrompt 2018年 ✅ 推荐使用 10+ 强生物识别 2019年+ 🔒 安全等级提升

2.1 Android 6.0:FingerprintManager 时代

先聊聊 FingerprintManager。这个 API 是 Android 6.0(API 23)引入的。我记得当时第一次在项目里用它,心里还挺美——终于不用跟各家厂商的指纹 SDK 打交道了。但用着用着就发现问题了。

核心问题是什么?FingerprintManager 只支持指纹识别。你想想看,如果手机有人脸识别、虹膜识别,它统统不认。而且它没有提供系统级的 UI 对话框,你得自己画指纹图标、自己处理动画。说白了,Google 只给了你一个「底层能力」,上层体验全靠自己搭。

⚠ 重要提醒:FingerprintManager 在 Android 9.0 之后已被标记为废弃(deprecated)。新项目不要再用了。如果你还在维护老代码,尽快迁移到 BiometricPrompt。

这里贴一段 FingerprintManager 的典型用法,你感受一下:

// Android 6.0 时代的写法(已废弃,仅供参考)
FingerprintManager fingerprintManager = 
    context.getSystemService(FingerprintManager.class);

if (fingerprintManager.isHardwareDetected()) {
    if (fingerprintManager.hasEnrolledFingerprints()) {
        // 开始认证...
        fingerprintManager.authenticate(
            null, 
            null, 
            0, 
            authenticationCallback, 
            null
        );
    }
}

看到没?代码里要自己检查硬件、自己检查是否录入指纹、自己处理回调。而且那个 null 参数传得我每次都要翻文档确认含义。嗯,这体验确实不太好。

2.2 Android 9.0:BiometricPrompt 登场

到了 Android 9.0(API 28),Google 终于想明白了。他们推出了 BiometricPrompt,把指纹、人脸、虹膜等所有生物识别方式统一到了一个 API 下面。我个人觉得,这是 Android 生物识别历史上最重要的一次更新。

BiometricPrompt 带来了什么?

  • 统一的认证对话框:系统帮你画好 UI,你只需要调起就行
  • 支持多种生物识别方式:指纹、人脸、虹膜,一个 API 全搞定
  • 更好的回调机制:认证成功、失败、错误,分得很清楚
  • 内置动画和提示:用户交互体验大幅提升

我在项目中遇到过这样一个场景:之前用 FingerprintManager 做的指纹登录,UI 是自己画的,结果不同厂商的手机上指纹图标位置不一样,适配起来特别痛苦。换成 BiometricPrompt 之后,这些问题全没了——系统帮你搞定一切。

💡 我的建议:如果你的 minSdkVersion 是 28 或以上,直接用 BiometricPrompt 就好。如果还要兼容老版本,可以用 AndroidX 的 Biometric 库,它提供了向下兼容的 BiometricPrompt。

看看 BiometricPrompt 的代码,是不是清爽多了:

// Android 9.0+ 的推荐写法
BiometricPrompt biometricPrompt = new BiometricPrompt(
    activity,
    executor,
    new BiometricPrompt.AuthenticationCallback() {
        @Override
        public void onAuthenticationSucceeded(
                BiometricPrompt.AuthenticationResult result) {
            // 认证成功,放行!
        }

        @Override
        public void onAuthenticationFailed() {
            // 认证失败,提示用户
        }

        @Override
        public void onAuthenticationError(int errorCode, CharSequence errString) {
            // 发生错误,比如用户取消、系统锁定等
        }
    }
);

BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
    .setTitle("指纹验证")
    .setSubtitle("请验证您的指纹")
    .setNegativeButtonText("取消")
    .build();

biometricPrompt.authenticate(promptInfo);

你看,代码结构清晰多了。不需要自己处理硬件检测,不需要自己画 UI,一个 authenticate() 调用就搞定了。

2.3 Android 10+:强生物识别

Android 10(API 29)开始,Google 引入了「强生物识别」的概念。为什么要搞这个?说白了,不是所有的生物识别都一样安全。

生物识别分三个等级:

等级 说明 典型场景
强(Strong) 满足 Android 最高安全标准,难以被欺骗 支付、解锁、敏感操作
弱(Weak) 安全性较低,可能被简单手段绕过 普通登录、个性化推荐
设备凭据(Device Credential) 使用 PIN、图案、密码 备用方案

我记得有一次做金融类 App,客户要求必须使用「强生物识别」才能进行支付操作。当时我查了一下文档,发现 BiometricPrompt 在 Android 10+ 上可以通过 setAllowedAuthenticators() 来指定安全等级。

关键点:Android 10+ 的 BiometricPrompt 允许你指定「只接受强生物识别」。如果设备只有弱生物识别(比如某些低端手机的人脸解锁),认证会直接失败。这在高安全场景下非常有用。

代码示例:

// Android 10+ 指定强生物识别
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
    .setTitle("支付验证")
    .setSubtitle("请使用指纹或人脸验证")
    .setAllowedAuthenticators(
        BiometricManager.Authenticators.BIOMETRIC_STRONG
        | BiometricManager.Authenticators.DEVICE_CREDENTIAL
    )
    .build();

这里 BIOMETRIC_STRONG 就是强生物识别。我还加上了 DEVICE_CREDENTIAL 作为备用——万一用户指纹坏了,还能用 PIN 码验证。

2.4 兼容性处理:让老设备也能用

好,现在问题来了:你的 App 要支持 Android 6.0 到 Android 14,怎么处理?

嗯,这里我直接说结论:用 AndroidX 的 Biometric 库。Google 官方已经帮我们做好了兼容性封装。

具体做法:

  1. build.gradle 中添加依赖:implementation 'androidx.biometric:biometric:1.2.0-alpha05'
  2. 代码中统一使用 androidx.biometric.BiometricPrompt
  3. 在 Android 6.0-8.1 的设备上,库会自动降级为指纹识别
  4. 在 Android 9.0+ 的设备上,使用完整的 BiometricPrompt 功能
  5. 在 Android 10+ 的设备上,支持强生物识别配置
⚠ 我曾经踩过的坑:早期版本的 AndroidX Biometric 库(1.0.x)在部分华为、小米手机上会出现对话框样式异常的问题。建议使用 1.1.0 及以上版本。另外,记得在调用 authenticate() 之前先检查 BiometricManager 的返回值,判断设备是否支持生物识别。

检查设备支持的代码:

// 检查设备是否支持生物识别
BiometricManager biometricManager = BiometricManager.from(context);
int canAuthenticate = biometricManager.canAuthenticate(
    BiometricManager.Authenticators.BIOMETRIC_STRONG
);

switch (canAuthenticate) {
    case BiometricManager.BIOMETRIC_SUCCESS:
        // 支持,可以调起认证
        break;
    case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
        // 没有生物识别硬件
        break;
    case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
        // 没有录入生物识别信息
        break;
    case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
        // 硬件暂时不可用
        break;
}

这个检查很重要。我曾经见过有 App 没做这个检查,在平板上直接调起 BiometricPrompt,结果弹了个空对话框,用户一脸懵。

2.5 总结:我推荐的做法

说了这么多,最后给你一个我目前在项目中实际使用的方案:

  • minSdkVersion = 23(Android 6.0)
  • 使用 AndroidX Biometric 库(版本 1.2.0+)
  • 统一使用 BiometricPrompt,不直接调用 FingerprintManager
  • 在 Android 10+ 上指定强生物识别,同时提供设备凭据作为备用
  • 调用前先检查 BiometricManager.canAuthenticate()

这样做的好处是:一套代码,兼容所有 Android 6.0+ 的设备。而且随着 Android 版本升级,你的代码不需要大改——因为 BiometricPrompt 本身就是 Google 主推的方向。

💡 最后一个小技巧:如果你的 App 对安全性要求极高(比如银行、支付类),建议在 Android 10+ 上强制使用 BIOMETRIC_STRONG,并且不要提供 DEVICE_CREDENTIAL 作为备用。这样即使用户的指纹坏了,也不能用 PIN 码绕过——虽然体验差一点,但安全性更高。

公众号:蓝海资料掘金营,微信deep3321