运用指纹

说明 : 指纹解锁在23 的时候,官方就现已给出了api ,但是由于Android商场复杂,无法构成统一,硬件由不同的厂商开发,导致相同版别的软件体系,搭载的硬件千变万化,导致由的机型不支撑指纹识别,但是,这也挡不住指纹识别在接下来的时刻中进入Android商场的趋势,由于它相比较输入暗码或图案,它愈加简单,相比较暗码或许图案,它更炫酷 ,本文Demo 运用最新的28 支撑的androidx 库中的API及最近炽热的kotlin言语完结的

需求知道的

  • FingerprintManager : 指纹管理工具类
  • FingerprintManager.AuthenticationCallback :运用验证的时候传入该接口,经过该接口进行验证结果回调
  • FingerprintManager.CryptoObject: FingerprintManager 支撑的分装加密方针的类

以上是28以下API 中运用的类 在Android 28版别中google 宣告运用Androidx 库替代Android库,所以在28版别中Android 引荐运用androidx库中的类 所以在本文中我 运用的是引荐是用的FingerprintManagerCompat 二者的运用的方式根本类似

如何运用指纹

  • 开端验证 ,体系默许的每段时刻验证指纹次数为5次 次数用完之后主动关闭验证,而且30秒之内不允行在运用验证

验证的办法是authenticate()

/**
*
*@param crypto object associated with the call or null if none required.
* @param flags optional flags; should be 0
* @param cancel an object that can be used to cancel authentication
* @param callback an object to receive authentication events
* @param handler an optional handler for events
**/
@RequiresPermission(android.Manifest.permission.USE_FINGERPRINT)
    public void authenticate(@Nullable CryptoObject crypto, int flags,
            @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback,
            @Nullable Handler handler) {
        if (Build.VERSION.SDK_INT >= 23) {
            final FingerprintManager fp = getFingerprintManagerOrNull(mContext);
            if (fp != null) {
                android.os.CancellationSignal cancellationSignal = cancel != null
                        ? (android.os.CancellationSignal) cancel.getCancellationSignalObject()
                        : null;
                fp.authenticate(
                        wrapCryptoObject(crypto),
                        cancellationSignal,
                        flags,
                        wrapCallback(callback),
                        handler);
            }
        }
    }

arg1: 用于经过指纹验证取出AndroidKeyStore中key的值 arg2: 体系主张为0

arg3: 取消指纹验证 手动关闭验证 能够调用该参数的cancel办法

arg4:返回验证结果

arg5: Handler fingerprint 中的 消息都是经过handler来传递的 假如不需求则传null 会主动默许创建一个主线程的handler来传递消息

运用指纹识别的条件

  • 添加权限(这个权限不需求在6.0中做处理)
  • 判别硬件是否支撑
  • 是否现已设置了锁屏 而且现已有一个被录入的指纹
  • 判别是否至少存在一条指纹信息

经过琐细的常识完结一个Demo

Android 指纹识别(给应用添加指纹解锁)

指纹识别经过之后跳转到 指定页面

进入之后首要弹出对话框,进行指纹验证

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/fingerprint" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:text="验证指纹" />
    <TextView
        android:id="@+id/fingerprint_error_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:maxLines="1" />
    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="5dp"
        android:background="#696969" />
    <TextView
        android:id="@+id/fingerprint_cancel_tv"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="取消"
        android:textSize="16sp" />
</LinearLayout>

运用DialogFragment 完结对话框 新建一个DialogFragment 而且初始化相关的api

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //获取fingerprintManagerCompat方针
        fingerprintManagerCompat = FingerprintManagerCompat.from(context!!)
        setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog)
    }

在界面显现在前台的时候开端扫描

override fun onResume() {
        super.onResume()
        startListening()
    }
@SuppressLint("MissingPermission")
    private fun startListening() {
        isSelfCancelled = false
        mCancellationSignal = CancellationSignal()
        fingerprintManagerCompat.authenticate(FingerprintManagerCompat.CryptoObject(mCipher), 0, mCancellationSignal, object : FingerprintManagerCompat.AuthenticationCallback() {
        //验证错误
            override fun onAuthenticationError(errMsgId: Int, errString: CharSequence?) {
                if (!isSelfCancelled) {
                    errorMsg.text = errString
                    if (errMsgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) {
                        Toast.makeText(mActivity, errString, Toast.LENGTH_SHORT).show()
                        dismiss()
                        mActivity.finish()
                    }
                }
            }
				//成功
            override fun onAuthenticationSucceeded(result: FingerprintManagerCompat.AuthenticationResult?) {
                MainActivity.startActivity(mActivity, true)
            }
			//错误时提示帮助,比如说指纹错误,咱们将显现在界面上 让用户知道情况
            override fun onAuthenticationHelp(helpMsgId: Int, helpString: CharSequence?) {
                errorMsg.text = helpString
            }
			//验证失败
            override fun onAuthenticationFailed() {
                errorMsg.text = "指纹验证失败,请重试"
            }
        }, null)
    }

在不行见的时候停止验证

if (null != mCancellationSignal) {
            mCancellationSignal.cancel()
            isSelfCancelled = true
        }

在MainActivity 中首要判别是否验证成功 是 跳转到方针页 不然的话需求进行验证 在这个过程中咱们需求做的便是判别是否支撑,判别是否满意指纹验证的条件(条件在上面)

if (intent.getBooleanExtra("isSuccess", false)) {
            WelcomeActivity.startActivity(this)
            finish()
        } else {
            //判别是否支撑该功用
            if (supportFingerprint()) {
                initKey() //生成一个对称加密的key
                initCipher() //生成一个Cipher方针
            }
        }

验证条件

 if (Build.VERSION.SDK_INT < 23) {
            Toast.makeText(this, "体系不支撑指纹功用", Toast.LENGTH_SHORT).show()
            return false
        } else {
            val keyguardManager = getSystemService(KeyguardManager::class.java)
            val managerCompat = FingerprintManagerCompat.from(this)
            if (!managerCompat.isHardwareDetected) {
                Toast.makeText(this, "体系不支撑指纹功用", Toast.LENGTH_SHORT).show()
                return false
            } else if (!keyguardManager.isKeyguardSecure) {
                Toast.makeText(this, "屏幕未设置锁屏 请先设置锁屏并添加一个指纹", Toast.LENGTH_SHORT).show()
                return false
            } else if (!managerCompat.hasEnrolledFingerprints()) {
                Toast.makeText(this, "至少在体系中添加一个指纹", Toast.LENGTH_SHORT).show()
                return false
            }
        }

必须生成一个加密的key 和一个Cipher方针

//生成Cipher
private fun initCipher() {
        val key = keyStore.getKey(DEFAULT_KEY_NAME, null) as SecretKey
        val cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                + KeyProperties.BLOCK_MODE_CBC + "/"
                + KeyProperties.ENCRYPTION_PADDING_PKCS7)
        cipher.init(Cipher.ENCRYPT_MODE, key)
        showFingerPrintDialog(cipher)
    }
    //生成一个key
private fun initKey() {
        keyStore = KeyStore.getInstance("AndroidKeyStore")
        keyStore.load(null)
        val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
        val builder = KeyGenParameterSpec.Builder(DEFAULT_KEY_NAME,
                KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
        keyGenerator.init(builder.build())
        keyGenerator.generateKey()
    }

Demo 是kotlin 写的 Demo地址