Android指纹校验与生物识别的使用

Android在6.0的时候提供了官方的指纹模块API,最近在使用的时候发现以前的FingerprintManager已经被标识为过时了。
在这里插入图片描述
Android 8.0 整合了一套生物识别模块,指纹识别使用BiometricPrompt来调用。
官方文档:FingerprintManager

官方文档:BiometricPrompt

写代码用过时API当然没排面啦,于是我转用了BiometricPrompt,但是也有一个问题,这个API是Android 28才能使用的,也就是说6.0,7.0的手机无法使用,7.0目前还是有一些使用率的,为了能够让所有支持指纹的Android手机都可以使用我两种方法都写了,使用策略模式封装了一下,直接看代码吧,使用Kotlin编写。

使用策略模式

关于策略模式的使用可以看我之前的这篇博客
策略模式

定义接口FingerPrintStrategy

interface FingerPrintStrategy {
    fun authenticate()//验证指纹
    fun cancelAuthenticate()//取消验证
}

定义回调接口

interface FingerprintResultCallback {
    fun onSucceeded(result:String)
    fun onFailed()
    fun onError(errorCode:Int,errorMessage:String)
}

FingerprintManager策略具体实现

@TargetApi(23)
class FingerprintStrategyForM(context: Context, callback: FingerprintResultCallback) : FingerPrintStrategy{
    private val TAG = "FingerprintStrategyForM"
    private val mContext = context
    private var mCancellationSignal: CancellationSignal? = null
    private var mFingerprintManager: FingerprintManager? = null
    private var mCipher: Cipher? = null
    private var mCallback:FingerprintResultCallback = callback
    init {
        mFingerprintManager = mContext.getSystemService(Context.FINGERPRINT_SERVICE) as FingerprintManager
        mCancellationSignal = CancellationSignal()
        mCancellationSignal!!.setOnCancelListener {
            PsyLog.d(TAG,"Canceled!!!")
        }
    }

	/**
	* 判断手机是否有指纹模块
	*/
    private fun hasFingerHardware():Boolean{
        if (mFingerprintManager == null){
            return false
        }
        return mFingerprintManager!!.isHardwareDetected
    }
	/**
	* 判断用户是否给手机录入过指纹
	*/
    private fun hasFingerInput():Boolean{
        if (mFingerprintManager == null){
            return false
        }
        return mFingerprintManager!!.hasEnrolledFingerprints()
    }
	/**
	* 指纹校验具体实现
	*/
    override fun authenticate() {
        if (!hasFingerHardware()){
            mCallback.onError(BIOMETRIC_ERROR_HW_NOT_PRESENT,mContext.getString(R.string.phone_no_biometric_sensor))
            return
        }
        if (!hasFingerInput()){
            mCallback.onError(BIOMETRIC_ERROR_NO_BIOMETRICS,mContext.getString(R.string.phone_not_input_fingerprint))
            return
        }
        mFingerprintManager?.authenticate(null,mCancellationSignal,0,object:FingerprintManager.AuthenticationCallback(){
            override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
                super.onAuthenticationError(errorCode, errString)
                mCallback.onError(errorCode,errString.toString())
            }

            override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult?) {
                super.onAuthenticationSucceeded(result)
                mCallback.onSucceeded(result.toString())
            }

            override fun onAuthenticationFailed() {
                super.onAuthenticationFailed()
                mCallback.onFailed()
            }
        },null)
    }
	/**
	* 取消校验
	*/
    override fun cancelAuthenticate() {
        mCancellationSignal?.cancel()
    }

}

BiometricPrompt策略具体实现

@TargetApi(28)
class FingerprintStrategyForP(context:Context, callback:FingerprintResultCallback):FingerPrintStrategy {
    private val TAG = "FingerprintStrategyForP"
    private val mContext:Context = context
    private var mCancellationSignal: CancellationSignal? = null
    private var mBiometricPrompt: BiometricPrompt? = null
    private var mAuthenticationCallback: BiometricPrompt.AuthenticationCallback? = null
    private val mCallback = callback
    init {
    	//setNegativeButton在这里是必须的,不写会报错,校验指纹是的UI必须有取消响应,此时按back键没用的
        mBiometricPrompt = BiometricPrompt.Builder(mContext)
            .setTitle(mContext.getString(R.string.authentication))
            .setDescription(mContext.getString(R.string.please_press_the_fingerprint_sensing_area_to_verify_the_fingerprint))
            .setNegativeButton(mContext.getString(R.string.cancel), getMainExecutor(mContext),
                DialogInterface.OnClickListener { dialog, which ->
                    PsyLog.d(TAG, "Cancel button clicked")
                    cancelAuthenticate()
                })
            .build()
        mCancellationSignal = CancellationSignal()
        mCancellationSignal!!.setOnCancelListener {
            PsyLog.d(TAG,"Canceled!!!")
        }

        mAuthenticationCallback = object : BiometricPrompt.AuthenticationCallback(){
        	//api版本判断,是否有指纹传感器等BiometricPrompt会自己判断,在这里返回
            override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
                super.onAuthenticationError(errorCode, errString)
                mCallback.onError(errorCode,errString.toString())
            }
			//校验成功
            override fun onAuthenticationFailed() {
                super.onAuthenticationFailed()
                mCallback.onFailed()
            }

            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult?) {
                super.onAuthenticationSucceeded(result)
                mCallback.onSucceeded(result.toString())
            }
        }

    }
	/**
	* 指纹校验具体实现
	*/
    override fun authenticate(){
        mBiometricPrompt!!.authenticate(mCancellationSignal!!, getMainExecutor(mContext), mAuthenticationCallback!!)
    }
	/**
	* 取消校验具体实现
	*/
    override fun cancelAuthenticate(){
        mCancellationSignal?.cancel()
    }

}

定义异常码

BiometricPrompt源码中就有很多异常码(官方文档中异常码定义
为了返回值统一我们可以给FingerprintManager也定义一样的异常码。

const val BIOMETRIC_ERROR_HW_NOT_PRESENT = 12
const val BIOMETRIC_ERROR_HW_UNAVAILABLE = 1
const val BIOMETRIC_ERROR_LOCKOUT = 7
const val BIOMETRIC_ERROR_LOCKOUT_PERMANENT = 9
const val BIOMETRIC_ERROR_NO_BIOMETRICS = 11
const val BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14
const val BIOMETRIC_ERROR_NO_SPACE = 4
const val BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15
const val BIOMETRIC_ERROR_TIMEOUT = 3

具体操作类

我的建的工程minSDK设置就是23,所以这里不用再判断版本号是否小于Android M了。如果你的minSDK比23小,需要再这里加一个判断,小于23直接返回。

class FingerPrintHelper(context: Context,fingerprintResultCallback: FingerprintResultCallback ) {
	//api 28 以下使用FingerprintManager策略,以上用BiometricPrompt策略
    private var strategy:FingerPrintStrategy = if (Build.VERSION.SDK_INT<Build.VERSION_CODES.P){
        FingerprintStrategyForM(context,fingerprintResultCallback)
    }else{
        FingerprintStrategyForP(context,fingerprintResultCallback)
    }
    
    fun authenticate(){
        strategy.authenticate()
    }

    fun cancelAuthenticate(){
        strategy.cancelAuthenticate()
    }
}

使用时使用如下代码就行了,

  FingerPrintHelper(mContext,
            object : FingerprintResultCallback {
                override fun onSucceeded(result: String) {
                    PsyLog.d(TAG, "onSucceeded")
                    //校验成功,跳转页面
                }

                override fun onFailed() {
                    PsyLog.d(TAG, "onFailed")
                    //每次指纹识别没通过都会走到这里

                }

                override fun onError(errorCode: Int, errorMessage: String) {
                    PsyLog.d(TAG, "onError")
                    showMessage(errorMessage)
                    //这里时一些错误情况,比如没有指纹传感器,错误太多指纹被锁等
                }
            }).authenticate()

FingerPrintHelper引用了context,记得在生命周期结束的时候释放掉,或者使用弱引用以防产生内存泄漏

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值