安卓学习笔记(20)-指纹识别API的简单运用与问题总结

0. 前言

​ 指纹识别的API在android6.0上提供了支持,部分的国内厂商也在部分的android6.0以下也自己加入了对指纹识别的功能。目前指纹识别得到了广泛的应用,如指纹解锁与支付等。下面我将android官方提供的一些接口进行使用,没有对其进行封装,旨在通过最简单的方式来了解这些API,以供与大家进行交流学习。

1. 官方API的说明

​ 在android.hardware.fingerprint下提供了四个类如下:

FingerprintManager 用于协调对指纹硬件设备的访问
FingerprintManager.AuthenticationCallback 通过回调函数authenticate来执行识别过程
FingerprintManager.AuthenticationResult 通过回调函数authenticate来获取数据(CryptoObject)
FingerprintManager.CryptoObject 这是一个FingerprintManager支持的加密对象的包装类

1.1 FingerprintManager

​ 我们进行指纹识别的开发,首先要获得FingerprintManager的实例,获取实例的方式有两种,分别是Context.getSystemService(Class)Context.getSystemService(Context.FINGERPRINT_SERVICE) 。在FingerprintManager中有三种方法:

  • authenticate(FingerprintManager.CryptoObject crypto, CancellationSignal cancel, int flags,FingerprintManager.AuthenticationCallback callback, Handler handler):通过调用这个方法来开始进行指纹识别。十分简单,在这个方法中我们看到需要

    FingerprintManager.CryptoObject参数,也就是加密对象,这个参数可以为null,但是不建议为null,因为不安全;

    CancellationSignal是用来在指纹识别器扫描用户指纹的是时候取消当前的扫描操作,如果不取消的话,那么指纹扫描器会移植扫描直到超时(一般为30s,取决于具体的厂商实现),这样的话就会比较耗电。建议这个参数不要置为null,这个参数的使用也很简单,稍后会介绍;

    int flags:这是一个标志位,需要置为0;

    FingerprintManager.AuthenticationCallback:用于接收authenticate的验证结果;

    Handler:FingerprintManager将会使用这个handler中的looper来处理来自指纹识别硬件的消息。通常来讲,开发这不用提供这个参数,可以直接置为null,因为FingerprintManager会默认使用app的main looper来处理。

  • hasEnrolledFingerprints():验证手机中是否已经存在指纹信息。所以如果手机里面没有录入指纹的话是不可以进行指纹识别的。这里也可以看出我们不可能开发一个使用手机指纹传感器采集指纹信息的APP,你只能使用这个传感器进行识别,而自己是不能监控采集与识别的过程的!!!

  • isHardwareDetected():用于判断设备是否支持指纹识别的功能

1.2 FingerprintManager.AuthenticationCallback

​ 这是回调函数类,我们在调用authenticate进行指纹识别时,会通过 FingerprintManager.AuthenticationCallback callback参数来返回识别信息,主要有以下的几个方法,这几个方法我们需要重写,以实现在不同的识别的结果下我们对应的功能实现。

  • onAuthenticationError(int errorCode, CharSequence errString):当遇到不可恢复的错误并且操作完成时调用。一般是错误次数超过系统预设的次数(一般是5次)或者其他原因导致的识别失败都会进入这个函数。

  • onAuthenticationFailed():单纯的因为识别失败(而非如手指上有污渍等原因)

  • onAuthenticationHelp(int helpCode, CharSequence helpString):在认证期间遇到可恢复的错误时调用。

  • onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result):识别成功!

1.3 FingerprintManager.AuthenticationResult

​ 这个类可以从cellback中获取数据,只有一个方法getCryptoObject()可以使用,他主要是获取那个加密信息,一般很少用到这个类。

1.4 FingerprintManager.CryptoObject

​ 这是一个加密类,加密的方式有对称加密和非对称加密,这一块的内容已经有博主写的非常详细了,见Android开发学习—指纹识别系统的原理与使用。我将会在下一篇博文中也详细的了解一下这一块的内容!

主要是有以下的三个类:

getCipher() Get Cipher object.
getMac() Get Mac object.
getSignature() Get Signature object.

2. API的简单使用

​ 要进行指纹识别,首先要添加权限:

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

​ 界面就简单的设置一个按钮开始指纹识别,xml我文件如下:

activity_main.xml:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context="cn.edu.xidian.fingerprinttest.MainActivity">

    <Button
        android:id="@+id/btn_finger"
        android:text="开始识别"
        android:textColor="#ffffff"
        android:background="#4fa5d5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

LinearLayout>

MainActivity.java

package cn.edu.xidian.fingerprinttest;

import android.app.KeyguardManager;
import android.content.Context;
import android.graphics.Color;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private Button btn_finger;
    private FingerprintManager mfingerprintManager = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_finger = findViewById(R.id.btn_finger);

        btn_finger.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //设置按钮颜色为灰色
                btn_finger.setText("开始指纹识别");
                btn_finger.setBackgroundColor(Color.parseColor("#8a8a8a"));

                //获取系统服务对象
                mfingerprintManager = (FingerprintManager)getSystemService(Context.FINGERPRINT_SERVICE);

                /**************************设备功能检测*****************************/
                //检测是否有指纹识别的硬件
                if (!mfingerprintManager.isHardwareDetected()){
                    Toast.makeText(MainActivity.this,"您手机没有指纹识别设备",Toast.LENGTH_SHORT).show();
                    return ;
                }
                //检测设备是否处于安全状态中
                KeyguardManager keyguardManager =(KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
                if (!keyguardManager.isKeyguardSecure()) {
                    //如果不是处于安全状态中,跳转打开安全保护(锁屏等)
                    return ;
                }
                //检测系统中是否注册的指纹
                if (!mfingerprintManager.hasEnrolledFingerprints()){
                    //没有录入指纹,跳转到指纹录入
                    Toast.makeText(MainActivity.this,"没有录入指纹!",Toast.LENGTH_SHORT).show();
                    return ;
                }

                /**************************开始指纹识别*****************************/
                mfingerprintManager.authenticate(null,cancellationSignal,0,myAuthCallback,null);

            }
        });
    }

    //初始化cancellationSignal类
    private CancellationSignal cancellationSignal = new CancellationSignal();
    //初始化MyAuthCallback
    private FingerprintManager.AuthenticationCallback myAuthCallback = new FingerprintManager.AuthenticationCallback() {
        @Override
        public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
            super.onAuthenticationSucceeded(result);

            btn_finger.setText("识别成功");
            btn_finger.setBackgroundColor(Color.parseColor("#4fa5d5"));
            Toast.makeText(MainActivity.this,"识别成功!",Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onAuthenticationFailed() {
            super.onAuthenticationFailed();

            Toast.makeText(MainActivity.this,"识别失败,请重试!",Toast.LENGTH_SHORT).show();

        }
    };
}

在代码中authenticate()函数的第一个参数,即加密类我设置为null,这种方式是不安全的,容易收到攻击,一般是不建议这样做的,我这里做实验就暂时设置为null吧。

在回调函数之中,我只重写了成功与失败的部分,其他功能各位尽可按照自己的要求来进行设置!

3. 效果图


安卓学习笔记(20)-指纹识别API的简单运用与问题总结_第1张图片 安卓学习笔记(20)-指纹识别API的简单运用与问题总结_第2张图片 安卓学习笔记(20)-指纹识别API的简单运用与问题总结_第3张图片

4. 一些问题总结

1、当指纹识别失败后,会调用onAuthenticationFailed()方法,这时候指纹传感器并没有关闭,谷歌原生系统给了我们5次重试机会,也就是说,连续调用了4次onAuthenticationFailed()方法后,第5次会调用onAuthenticateError(int errMsgId, CharSequence errString)方法,此时errMsgId==7。

2、每次重新授权,哪怕不去校验,取消时会走onAuthenticateError(int errMsgId, CharSequence errString) 方法,其中errMsgId==5,

3、当系统调用了onAuthenticationError()和onAuthenticationSucceeded()后,传感器会关闭,只有我们重新授权,再次调用authenticate()方法后才能继续使用指纹识别功能。

4、兼容android6.0以下系统的话,不要使用FingerprintManagerCompat, 低于M的系统版本,FingerprintManagerCompat无论手机是否有指纹识别模块,均认为没有指纹识别,可以用FingerprintManager来做。

5、考虑到安全因素,最好authenticate(CryptoObject crypto, CancellationSignal cancel, int flags, AuthenticationCallback callback, Handler handler)时加入CryptoObject 。crypto这是一个加密类的对象,指纹扫描器会使用这个对象来判断认证结果的合法性。这个对象可以是null,但是这样的话,就意味着app无条件信任认证的结果,这个过程可能被攻击,数据可以被篡改,这是app在这种情况下必须承担的风险。因此,建议这个参数不要置为null。这个类的实例化有点麻烦,主要使用javax的security接口实现。

6、最后一步就是开始等待验证指纹。系统默认每段时间内验证指纹次数为5次,如果5次后还没验证成功,则关闭验证,并且30秒内不允许再次验证,即使你调api也没用

5.源代码见github

github

你可能感兴趣的:(android,安卓学习笔记)