美文网首页
Android指纹识别

Android指纹识别

作者: ReleaseYH | 来源:发表于2018-04-10 09:19 被阅读0次

    指纹识别大致应用在几种场景
    1,系统解锁
    2,应用锁
    3,支付认证
    4,普通的登录认证

    指纹识别需要手机硬件支持才能使用。核心的API 是FingerprintManager。主类依赖三个内部类,
    1,FingerprintManager.AuthenticationResult 指纹识别结果封装,从回调接口里面会传回来
    2, FingerprintManager.CryptoObject 指纹识别数据传输加密对象
    3, FingerprintManager.AuthenticationCallback 指纹识别成功、失败、错误的回调接口。

    FingerprintManager 提供3个方法
    启动指纹识别


    2.png

    这里cancel参数是用来主动取消指纹识别的。handle是默认会在主线程运行。

    判断是否至少录入一个指纹


    3.png

    判断是否有硬件支持


    4.png

    有这些方法就可以尝试下代码编写了。
    1,首先 AndroidManifest权限声明权限

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

    2,获取FingerManager服务对象

      public static FingerprintManager getFingerprintManager(Context context) {
      FingerprintManager fingerprintManager = null;
        try {
            fingerprintManager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
          } catch (Throwable e) {
            L.v("have not class FingerprintManager");
          }
            return fingerprintManager;
      }
    
    1. 启动指纹识别
      mFingerprintManager.authenticate(cryptoObject, mCancellationSignal, 0, mAuthCallback, null);
    

    参数意思参考文档说明,这里比较复杂的是创建CryptoObject对象,如果只是简单测试可以为null。

    官方v4兼容包
    上面介绍是官方实现指纹识别的方式,当然适配肯定没这么简单,因为有很多设备兼容性要考虑,Google后续再v4包中提供了一套完整的实现,实现类与上面的一一对应的,就是改了个名字(FingerprintManager改为了FingerprintManagerCompat,所以Google在v4包中做了一些兼容性处理),做了很多兼容处理,官方推荐使用后者。

    下面是一些相关的注意点或者说是一些会遇到的坑。
    1,Google官方支持指纹识别的标准接口是在Android6.0开始的,如果各个厂商都升级到6.0并且硬件上都给予支持,那么我们按照标准的指纹识别接口使用就可以了。
    2,如果在android6.0发布以后,手机厂商来不及升级,但是工程师们参考了官方指纹识别的代码,把代码移植到他们的6.0版本以下的系统,或者参照Google提供的接口自己实现了一套指纹识别机制,只是对开发者暴露的接口一样,这样就可以像使用标准接口一样使用,但是这种情况就难说了,实现不好的可能本身就有很多bug,适配起也比较麻烦,不过起码还是能用的。
    3,如果厂商在Google之前就已经做了指纹识别,那这种情况肯定不能使用官方标准接口,如果要适配这种设备,只能使用厂商提供的第三方指纹识别SDK。

    所以建议 6.0及以上系统选择性屏蔽一些机型(有些厂商支持不好)
    这里CryptoObject的初始化工作。

        private void initCryptoObject() {
        try {
            mCryptoObjectCreator = new CryptoObjectCreator(new CryptoObjectCreator.ICryptoObjectCreateListener() {
                @Override
                public void onDataPrepared(FingerprintManager.CryptoObject cryptoObject) {
                    // startAuthenticate(cryptoObject);
                    // 如果需要一开始就进行指纹识别,可以在秘钥数据创建之后就启动指纹认证
                }
            });
        } catch (Throwable throwable) {
            FPLog.log("create cryptoObject failed!");
        }
    }
    

    CryptoObjectCreator类

     @TargetApi(Build.VERSION_CODES.M)
    public class CryptoObjectCreator {
        private static final String KEY_NAME = "crypto_object_fingerprint_key";
    
        private FingerprintManager.CryptoObject mCryptoObject;
        private KeyStore mKeyStore;
        private KeyGenerator mKeyGenerator;
        private Cipher mCipher;
    
        public interface ICryptoObjectCreateListener {
            void onDataPrepared(FingerprintManager.CryptoObject cryptoObject);
        }
    
        public CryptoObjectCreator(ICryptoObjectCreateListener createListener) {
            mKeyStore = providesKeystore();
            mKeyGenerator = providesKeyGenerator();
            mCipher = providesCipher(mKeyStore);
            if (mKeyStore != null && mKeyGenerator != null && mCipher != null) {
                mCryptoObject = new FingerprintManager.CryptoObject(mCipher);
            }
            prepareData(createListener);
        }
    
        private void prepareData(final ICryptoObjectCreateListener createListener) {
            new Thread("FingerprintLogic:InitThread") {
                @Override
                public void run() {
                    try {
                        if (mCryptoObject != null) {
                            createKey();
                            // Set up the crypto object for later. The object will be authenticated by use
                            // of the fingerprint.
                            if (!initCipher()) {
                                FPLog.log("Failed to init Cipher.");
                            }
                        }
                    } catch (Exception e) {
                        FPLog.log(" Failed to init Cipher, e:" + Log.getStackTraceString(e));
                    }
                    if (createListener != null) {
                        createListener.onDataPrepared(mCryptoObject);
                    }
                }
            }.start();
        }
    
    /**
     * Creates a symmetric key in the Android Key Store which can only be used after the user has
     * authenticated with fingerprint.
     */
    private void createKey() {
        // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
        // for your flow. Use of keys is necessary if you need to know if the set of
        // enrolled fingerprints has changed.
        try {
            mKeyStore.load(null);
            // Set the alias of the entry in Android KeyStore where the key will appear
            // and the constrains (purposes) in the constructor of the Builder
            mKeyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME,
                    KeyProperties.PURPOSE_ENCRYPT |
                            KeyProperties.PURPOSE_DECRYPT)
                    .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                    // Require the user to authenticate with a fingerprint to authorize every use
                    // of the key
                    .setUserAuthenticationRequired(true)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                    .build());
            mKeyGenerator.generateKey();
        } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
                | CertificateException | IOException e) {
            FPLog.log(" Failed to createKey, e:" + Log.getStackTraceString(e));
            throw new RuntimeException(e);
        }
    }
    
    /**
     * Initialize the {@link Cipher} instance with the created key in the {@link #createKey()}
     * method.
     *
     * @return {@code true} if initialization is successful, {@code false} if the lock screen has
     * been disabled or reset after the key was generated, or if a fingerprint got enrolled after
     * the key was generated.
     */
    private boolean initCipher() {
        try {
            mKeyStore.load(null);
            SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null);
            mCipher.init(Cipher.ENCRYPT_MODE, key);
            return true;
        } catch (KeyPermanentlyInvalidatedException e) {
            FPLog.log(" Failed to initCipher, e:" + Log.getStackTraceString(e));
            return false;
        } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
                | NoSuchAlgorithmException | InvalidKeyException e) {
            FPLog.log(" Failed to initCipher, e :" + Log.getStackTraceString(e));
            throw new RuntimeException("Failed to init Cipher", e);
        }
    }
    
    public static KeyStore providesKeystore() {
        try {
            return KeyStore.getInstance("AndroidKeyStore");
        } catch (Throwable e) {
            return null;
        }
    }
    
    public static KeyGenerator providesKeyGenerator() {
        try {
            return KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
        } catch (Throwable e) {
            return null;
        }
    }
    
    public static Cipher providesCipher(KeyStore keyStore) {
        try {
            return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                    + KeyProperties.BLOCK_MODE_CBC + "/"
                    + KeyProperties.ENCRYPTION_PADDING_PKCS7);
        } catch (Throwable e) {
            return null;
        }
    }
    
    public FingerprintManager.CryptoObject getCryptoObject() {
        return mCryptoObject;
    }
    
    public void onDestroy() {
        mCipher = null;
        mCryptoObject = null;
        mCipher = null;
        mKeyStore = null;
        }
    }
    

    下面是效果图


    5.png

    点击按钮启动指纹识别之后识别指纹。成功。


    6.png

    当然,这只是简单指纹识别功能。具体可以根据业务开发。结合登录或者一些需要安全验证的操作。就可以提高用户体验。

    相关文章

      网友评论

          本文标题:Android指纹识别

          本文链接:https://www.haomeiwen.com/subject/jnzwhftx.html