Android在6.0的时候提供了官方的指纹模块API,最近在使用的时候发现以前的FingerprintManager已经被标识为过时了。
Android指纹校验与生物识别的使用_第1张图片
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 = 12const val BIOMETRIC_ERROR_HW_UNAVAILABLE = 1const val BIOMETRIC_ERROR_LOCKOUT = 7const val BIOMETRIC_ERROR_LOCKOUT_PERMANENT = 9const val BIOMETRIC_ERROR_NO_BIOMETRICS = 11const val BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14const val BIOMETRIC_ERROR_NO_SPACE = 4const val BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15const 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,记得在生命周期结束的时候释放掉,或者使用弱引用以防产生内存泄漏

更多相关文章

  1. android 自定义Adapter的心得
  2. Android自定义Seekbar拖动条式样
  3. 【Android】Aidl使用详解(支持多个回调和传递自定义对象)
  4. Android 中自定义View的应用.
  5. Androidの自定义圆角按钮button
  6. android自定义Toast之-弹出消息

随机推荐

  1. vue使用axios报404错误:Uncaught (in prom
  2. 我采访了一位 Pornhub 工程师,聊了这些纯
  3. 一个 Java 字符串到底有多少个字符?
  4. 别在 Java 代码里乱打日志了,这才是正确的
  5. 不想 CRUD 干到老,就来看看这篇 OOM 排查
  6. Django源代码-启动、接收、应用中间件链
  7. 适用于Windows和Mac的15种最佳免费代码编
  8. 无视社区担忧,JPMS(Jigsaw)将被提交公开预览
  9. java编程基础-Java多线程的调度
  10. 轻轻松松看电影,这几行python代码帮你搞定