Android指纹登录

1、介绍

指纹登录可以实现应用的快捷登录,在Android6.0谷歌才提供统一指纹SDK接口,在6.0之前都是各个厂商自定义。

2、使用

下面介绍如何在我们的应用中加入指纹登录的功能,之前实现指纹解锁都是用的FingerprintManager类,FingerprintManager在最新的Android 9.0系统上已经被废弃了,当Google在v4包中把FingerprintManager改为了FingerprintManagerCompat,而Compat是兼容的意思,所以Google在v4包中做了一些兼容性处理,官方推荐使用后者。所以本demo用的就是FingerprintManagerCompat工具类。
一、申请权限



二、验证手机是否支持指纹,如果手机不支持,那就没办法了。

FingerprintManagerCompat提供了三个方法:

  • isHardwareDetected() 判断是否有硬件支持
  • isKeyguardSecure() 判断是否设置锁屏,因为一个手机最少要有两种登录方式
  • hasEnrolledFingerprints() 判断系统中是否添加至少一个指纹
/**
* 判断是否支持指纹识别
*/
public static boolean supportFingerprint(Context mContext) {
    if (Build.VERSION.SDK_INT < 23) {
        Toast.makeText(mContext, "您的系统版本过低,不支持指纹功能", Toast.LENGTH_SHORT).show();
        return false;
    } else {
        KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
        FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(mContext);
        if (!fingerprintManager.isHardwareDetected()) {
            Toast.makeText(mContext, "您的系统版本过低,不支持指纹功能", Toast.LENGTH_SHORT).show();
            return false;
        } else if (keyguardManager != null && !keyguardManager.isKeyguardSecure()) {
            Toast.makeText(mContext, "您的手机不支持指纹功能", Toast.LENGTH_SHORT).show();
            return false;
        } else if (!fingerprintManager.hasEnrolledFingerprints()) {
            Toast.makeText(mContext, "您至少需要在系统设置中添加一个指纹", Toast.LENGTH_SHORT).show();
            return false;
        }
    }
    return true;
}

三、开启指纹登录,一般来说都是弹出个提示框用于显示指纹识别的状态。
首先,生成一个对称加密的key

private static final String DEFAULT_KEY_NAME = "default_key";

@TargetApi(23)
private void initKey() {
    try {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
        KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(DEFAULT_KEY_NAME,
                KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);
        keyGenerator.init(builder.build());
        keyGenerator.generateKey();
        initCipher(keyStore);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

然后,通过生成的key初始化生成一个Cipher对象

@TargetApi(23)
private void initCipher(KeyStore keyStore) {
    try {
        SecretKey key = (SecretKey) keyStore.getKey(DEFAULT_KEY_NAME, null);
        Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                + KeyProperties.BLOCK_MODE_CBC + "/"
                + KeyProperties.ENCRYPTION_PADDING_PKCS7);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        showFingerPrintDialog(cipher);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

最后,通过上面生成的Cipher去开启指纹验证

private void showFingerPrintDialog(Context context, Cipher cipher) {
    FingerprintManagerCompat fingerprintManagerCompat = FingerprintManagerCompat.from(context);
    FingerprintManagerCompat.CryptoObject cryptoObject = new FingerprintManagerCompat.CryptoObject(cipher);
    CancellationSignal mCancellationSignal = new CancellationSignal();
    //识别过程中可以手动取消指纹识别
    //mCancellationSignal.cancel();
    fingerprintManagerCompat.authenticate(cryptoObject, 0, mCancellationSignal, new MyCallBack(), null);
}

下面详细说一下,刚才开启指纹验证的时候的步骤:
1、创建一个FingerprintManagerCompat对象,上面有说到谷歌已经不推荐使用FingerprintManager类。

FingerprintManagerCompat fingerprintManagerCompat = FingerprintManagerCompat.from(context);

2、拿到FingerprintManagerCompat对象后就可以调authenticate方法进行指纹识别了,这里面需要传递几个参数:
(1)CryptoObject 这是一个加密类的对象,指纹扫描器会使用这个对象来判断认证结果的合法性。这个对象可以是null,但是这样的话,就意味这app无条件信任认证的结果,虽然从理论上这个过程可能被攻击,数据可以被篡改,这是app在这种情况下必须承担的风险。因此,建议这个参数不要置为null。这里就需要使用之前初始化的Cipher去创建一个CryptoObject 对象。

FingerprintManagerCompat.CryptoObject cryptoObject = new FingerprintManagerCompat.CryptoObject(cipher);

(2)flags 标识位,这个标志位应该是保留将来使用的,在这里我们传0就可以了。
(3)cancel这个是CancellationSignal类的一个对象,这个对象用来在指纹识别器扫描用户指纹的是时候取消当前的扫描操作,如果不取消的话,那么指纹扫描器会移植扫描直到超时(一般为30s,取决于具体的厂商实现),这样的话就会比较耗电。建议这个参数不要置为null。识别过程中可以手动取消指纹识别。

CancellationSignal mCancellationSignal = new CancellationSignal();
//识别过程中可以手动取消指纹识别
//mCancellationSignal.cancel();

(4)callback这个参数很重要,看名字就知道这是个回调的接口,这个参数等最后我们详细来介绍。这个参数不能为null。
(5)handler这是Handler类的对象,FingerprintManagerCompat将会使用这个handler中的looper来处理来自指纹识别硬件的消息。一般来说,我们开发的时候可以直接传null,因为FingerprintManagerCompat会默认使用app的main looper来处理。
3、最后我们来说一下刚才的callback这个参数

public class MyCallBack extends FingerprintManagerCompat.AuthenticationCallback {

   @Override
   public void onAuthenticationError(int errMsgId, CharSequence errString) {
       //当出现错误的时候回调此函数,比如多次尝试都失败了的时候,errString是错误信息
       //一般来说我们都是先判断一下是不是自己手动取消
       Log.e("TAG", "errMsgId=" + errMsgId);
       if (errMsgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) {
           Log.e("TAG", "" + errString);
       }
   }

   //当指纹验证失败的时候会回调此函数,失败之后允许多次尝试,失败次数过多会停止响应一段时间然后再停止sensor的工作
   @Override
   public void onAuthenticationFailed() {
       //指纹认证失败,请再试一次
       Log.e("TAG", "onAuthenticationFailed");
   }

   @Override
   public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
      //错误时提示帮助,比如说指纹错误,我们将显示在界面上 让用户知道情况
      Log.e("TAG", "helpString=" + helpString);
   }

   //当验证的指纹成功时会回调此函数,然后不再监听指纹sensor
   @Override
   public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
       //这里我们可以做取消弹框之类的
       Log.e("TAG", "onAuthenticationSucceeded=" + result.toString());
   }
}

四、总结
以上就是一个开发指纹识别的基本过程,希望对大家有所帮助。。。

你可能感兴趣的:(Android指纹登录)