Android 指纹识别(给应用添加指纹解锁)
使用指纹
说明 : 指纹解锁在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: 系统建议为0arg3: 取消指纹验证 手动关闭验证 可以调用该参数的cancel方法
arg4:返回验证结果
arg5: Handler fingerprint 中的
消息都是通过handler来传递的 如果不需要则传null 会自动默认创建一个主线程的handler来传递消息
使用指纹识别的条件
- 添加权限(这个权限不需要在6.0中做处理)
- 判断硬件是否支持
- 是否已经设置了锁屏 并且已经有一个被录入的指纹
- 判断是否至少存在一条指纹信息
通过零碎的知识完成一个Demo
指纹识别通过之后跳转到 指定页面
进入之后首先弹出对话框,进行指纹验证
<?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对象
//生成Cipherprivate 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) } //生成一个keyprivate 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地址
转载请著名 图你怀中安稳 https://blog.csdn.net/qq_32648731/article/details/82385031
更多相关文章
- Android指纹识别
- Android 学习笔记--android――Activity跳转条件不匹配出现FC,规
- Android 如何开发指纹支付
- Android指纹校验与生物识别的使用
- android密码解锁/指纹解锁返回的authToken深度解剖
- Android O 指纹识别解析
- 25000字总结Android优秀的第三方框架、各种学习资料汇集 二 Came
- 指纹识别分析之enroll流程
- Android 指纹识别