Android指纹校验与生物识别的使用
16lz
2021-01-23
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 = 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,记得在生命周期结束的时候释放掉,或者使用弱引用以防产生内存泄漏。
更多相关文章
- android 自定义Adapter的心得
- Android自定义Seekbar拖动条式样
- 【Android】Aidl使用详解(支持多个回调和传递自定义对象)
- Android 中自定义View的应用.
- Androidの自定义圆角按钮button
- android自定义Toast之-弹出消息