指纹登录 - FingerprintManager

最近项目中添加了一个新的登录方式:指纹识别。好巧不巧这块分给了我,然后一顿研究。下面想把一些实现的代码贴出来做个笔记,加深下印象。
先来介绍下指纹识别,指纹识别是Google从Android6.0(api23)开始才提供的标准指纹识别支持,并对外提供指纹识别相关的接口。

一开始我在理解指纹识别的时候有几个误区:
①我认为指纹识别,哇,这么高大上,应该是一个第三方的SDK,需要引入第三方来做,就和我们做刷脸识别引入了百度的SDK一样。后来发现是我想复杂了,指纹识别是Android6.0以上就开始支持的一个功能,并且类也不多,主要就是FingerprintManager还有它里面三个内部类(AuthenticationCallback、AuthenticationResult、CryptoObject),后面细讲。

②我认为指纹识别应该是在自己的APP里面既能录入又能识别,把指纹数据放到APP的储存中。后来发现也不是我想的那样,首先明确的一点是指纹数据是在手机的设置里面,不是存到自己写的APP的。其次,指纹识别就只能识别,而不能在APP中录入指纹,想录入指纹可以,自己要到手机设置里面的指纹功能自己去添加,指纹识别功能能做的就是把用户放到感应区的指纹数据与手机设置里面的已录入的指纹数据进行比对,再执行成功失败的回调,仅此而已。

③我认为指纹识别会很难。其实不然,如果你只是要指纹的识别结果,而不是深入的研究它的加密了(CryptoObject),指纹列表的变化监听(这个大致说一下啥意思,在一些场景中,需要对用户手机里面录入的指纹进行监听,当用户手机里面的指纹列表发生了变化,比如用户删除了指纹或者新增了指纹,就需要用户重新输入密码,这就需要指纹变化的监听,记录用户手机里面的指纹 ID,并进行前后对比,才能实现。这种情况在APP中很常见,拿支付宝说,我本来手机中只录入了我右手的食指指纹,我习惯右手玩手机,但后来我又录入了左手的食指指纹,这时候我再使用支付宝的指纹付款,它就会弹出我的支付密码框,让我输入我的支付密码),它就没多少东西,像我们项目中,只是对指纹做了个比对,把结果拿到而已,那就非常简单。话不多说,下面直接上代码。


指纹开启前提

这里插一嘴,介绍一下FingerprintManager类,它是Google提供的帮助访问指纹硬件的API类,主要有三个方法:


三个主要的方法

第一个方法:启动指纹识别(先稍作忽略,后面讲)
第二个方法:判断手机里面是否有已经有录入的指纹(至少得有一个)
第三个方法:判断手机是否有指纹感应区(硬件支持)
ok 继续!

①检查权限
Android清单文件中的指纹的权限是

<uses-permission android:name="android.permission.USE_FINGERPRINT"/>

你查资料就会发现这个权限它是NormalPermissions,它不是DangerousPermissions 按理说不用考虑6.0的动态权限问题,只要在清单文件中添加一下即可。但是Android厂家定制的系统很多很多,可能有些系统不一定会默认分配指纹权限,比如上几篇中文章中那款傻逼vivo6.0的动态权限,简直就是胡改瞎改。以防万一,还是检查下吧,以防万一!

@NeedsPermission(Manifest.permission.USE_FINGERPRINT)
void showFingerDilaog(){
    //去开启指纹识别操作
}

@OnNeverAskAgain(Manifest.permission.USE_FINGERPRINT)
void showNeverAskForCall() {
    //点击了不再询问按钮的回调
    //低版本手机不支持指纹识别的也会走这个回调
}

@OnPermissionDenied(Manifest.permission.USE_FINGERPRINT)
void showRefuseForCall() {
     //点击了禁止按钮的回调
}

我把项目中检测权限的代码贴到这里(算是伪代码吧,只看逻辑即可),我们用到的是PermissionsDispatcher来检测动态权限问题的,当然,关于动态权限的框架很多,像我前几篇文章的那个RXPermissions也是一种办法,这里动态权限方法挑适合自己的即可。

②检查手机硬件(有没有指纹感应区)

if (!mManager.isHardwareDetected()) {
    Toast.makeText(mContext, "没有指纹识别模块", Toast.LENGTH_SHORT).show();
    return false;
}

这个mManager就是FingerprintManager对象,用上面图片中它的第三个方法即可判断,很简单,没什么可说的

③检查手机是否开启锁屏密码
为什么要检查这个呢?因为Android6.0以上的手机添加指纹前,必须要先启锁屏密码,以免不能使用指纹时,用户还可以采用其他方法打开手机。

if (!mKeyManager.isKeyguardSecure()) {
    Toast.makeText(mContext(), "没有开启锁屏密码", Toast.LENGTH_SHORT).show();
    return false;
}

这个mKeyManager就是KeyguardManager的对象,它的作用就是对Keyguard进行管理,即对锁屏进行管理。在这里它的作用只是判断用户手机是否设置了锁屏密码。

④检查手机是否已录入指纹
这个很好理解,指纹识别,手机里总得先有指纹供检测吧。

if (!mManager.hasEnrolledFingerprints()) {
    Toast.makeText(mContext, "没有指纹录入", Toast.LENGTH_SHORT).show();
    return false;
}

这个是上面图片中它的第二个方法。好了,到这里,我们把上面的几个方法结合一起,就能写出一个完整的手机指纹识别开启的检测条件:

@TargetApi(23)
public boolean judgeFingerprintIsCorrect() {
    //判断硬件是否支持指纹识别
    if (!mManager.isHardwareDetected()) {
        Toast.makeText(mContext, "没有指纹识别模块", Toast.LENGTH_SHORT).show();
        return false;
    }
    //判断是否开启锁屏密码
    if (!mKeyManager.isKeyguardSecure()) {
        Toast.makeText(mContext, "没有开启锁屏密码", Toast.LENGTH_SHORT).show();
        return false;
    }
    //判断是否有指纹录入
    if (!mManager.hasEnrolledFingerprints()) {
        Toast.makeText(mContext, "没有指纹录入", Toast.LENGTH_SHORT).show();
        return false;
    }
    return true;
}

这里需要注意一下,FingerprintManager对象的isHardwareDetected()方法和hasEnrolledFingerprints()方法需要API级别为23及以上,如果你的API级别小于23,那就得加上@TargetApi(23)

创建指纹开启的回调方法

这里就该引入上面所说的FingerprintManager的三个内部类了

①FingerPrintManager.AuthenticationCallback:
在验证时传入该接口,通过该接口来返回验证指纹的结果

②FingerPrintManager.AuthenticationResult:
当指纹验证正确时,接口里返回的参数

③FingerPrintManager.CryptoObject:
由FingerPrintManager支持的封装加密对象的类

上面我们说到,如果你只要指纹识别的结果,其他的功能不关系,那就很简单,只要和AuthenticationCallback类打交道即可。这一步我们就创建AuthenticationCallback类对象,上代码

FingerprintManager.AuthenticationCallback mSelfCancelled = new FingerprintManager.AuthenticationCallback() {
    @Override
    public void onAuthenticationError(int errorCode, CharSequence errString) {
        //多次指纹密码验证错误后,进入此方法;并且,不可再验(短时间)
        //errorCode是失败的次数
        ToastUtils.show(mContext, "尝试次数过多,请稍后重试", 3000);
    }

    @Override
    public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
        //指纹验证失败,可再验,可能手指过脏,或者移动过快等原因。
    }

    @Override
    public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
        //指纹密码验证成功
    }

    @Override
    public void onAuthenticationFailed() {
        //指纹验证失败,指纹识别失败,可再验,错误原因为:该指纹不是系统录入的指纹。
    }
};

开启指纹识别

接下来,我们将指纹识别的CallBack绑定到FingerprintManager中,以获得指纹识别的结果。这就得引入上面图片中FingerprintManager的第一个方法:

/**
 * 参数说明:
 * FingerprintManager.CryptoObject - 用于通过指纹验证取出AndroidKeyStore中的key的对象,用于加密
 * CancellationSignal - 用来取消指纹验证,如果想手动关闭验证,可以调用该参数的cancel方法
 * int - 没什么意义,就是传0就好了
 * FingerprintManager.AuthenticationCallback -  最重要,由于指纹信息是存在系统硬件中的,app是不可以访问指纹信息的,所以每次验证的时候,系统会通过这个callback告诉你是否验证通过、验证失败等
 * Handler - FingerPrint中的消息都通过这个Handler来传递消息,如果你传空,则默认创建一个在主线程上的Handler来传递消息,没什么用,传null好了
 */
public void authenticate(FingerprintManager.CryptoObject crypto, CancellationSignal cancel, int flags, FingerprintManager.AuthenticationCallback callback, Handler handler)

像我们项目中的代码如下:

mManager.authenticate(null, mCancellationSignal, 0, mSelfCancelled, null);

可以看到,这个方法中传递了一个AuthenticationCallback,用于获取指纹识别结果 ,传递了一个CancellationSignal(后面再说)。OK,至此,指纹识别已经开启了。

取消指纹识别

当我们指纹识别完了,拿到我们想要的结果了,那我们要怎么样取消指纹识别呢?
这就需要用到CancellationSignal 类了,就是我们上面代码中的第二个参数。上代码:

CancellationSignal mCancellationSignal = new CancellationSignal();

...

mManager.authenticate(null, mCancellationSignal, 0, mSelfCancelled, null);

...

//取消指纹识别
mCancellationSignal.cancel();

可以看出取消指纹识别很简单,authenticate方法中的第二个参数是一个CancellationSignal对象,这个对象就是用来维护取消操作的,这些操作包括取消监听和设定取消回调等。所以,如果要取消,这个参数就不能传Null。
这里补充一点哈,当执行取消指纹识别之后

//取消指纹识别
mCancellationSignal.cancel();

会执行的回调方法是:

onAuthenticationError()

也就是说,手动取消指纹识别,和多次验证失败走的方法是一样的。


简单的指纹识别应用到此就说的差不多了,当然,这只是简单应用而已。指纹这块还有很多很多东西等着我们去学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容