前言
现在越来越多的 app 会用到锁屏暗码验证或者生物辨认(指纹辨认、面庞辨认),最常见的场景便是各大银行登录的时分为了免密登录而设置的验证,目的是为了验证是否是自己操作。
另一种场景便是跟本文所叙述的一样,在用户忘记暗码的时分能够经过体系暗码(也便是锁屏暗码与生物辨认)验证身份然后进行暗码的修正,不然便是类似于QQ一样,需求申述或者经过密保找回。
运用到的类
KeyguardManager
这个类是 Android SDK 中自带的,目的是对 Keyguard 进行办理,即对锁屏进行办理,本文首要用到下面几个方法:
-
isDeviceSecure:判别设备是否设置了锁屏暗码(包括 PIN 码、解锁图画或数字暗码),只能用于
Android 6.0
以上。 -
isKeyguardSecure:与 isDeviceSecure 一样,差异在于比 isDeviceSecure 多了一个 SIM 卡确定的判别,以及对版别的兼容,能够兼容到
Android 3.2
以上。 -
createConfirmDeviceCredentialIntent:创立并弹出锁屏暗码验证框。
Biometric库
这是Google提供的生物辨认的库,文档传送门
在 Android 6.0 的时分SDK引入了 FingerprintManager
作为指纹辨认的办理类,但是在 Android 9.0 的时分废弃了,然后运用 Biometric 库来代替,库中现已包括了所有需求添加的权限,所以能够直接引入依靠并运用。
implementation 'androidx.biometric:biometric:1.1.0'
声明身份验证类型:
-
BIOMETRIC_STRONG:运用Android 兼容性界说页面上界说的3 类生物辨认技能进行身份验证,简略来说便是支撑加密密钥运用。
-
BIOMETRIC_WEAK:运用Android 兼容性界说页面上界说的2 类生物辨认技能进行身份验证,简略来说便是一般的验证,不需求进行加密。
-
DEVICE_CREDENTIAL:运用屏幕确定凭据(即用户的 PIN 码、解锁图画或暗码)进行身份验证。(Android 10 以上可用)
锁屏暗码
上面介绍了需求用到的类,以及引入了 Biometric 库的依靠了,那么现在能够开始码代码了。
对于锁屏暗码,咱们需求先判别设备的 Android 版别(假如咱们的项目中的 minSdk 为23或以上的话,能够疏忽这部分内容,直接只运用 BiometricPrompt 方法),当 Android 版别小于 10 的话,咱们运用 KeyguardManager 来进行锁屏暗码验证,当 Android 版别大于 10 的话,咱们一致运用 Biometric 库来进行锁屏暗码验证,这也是 Google 推荐的方法。
下面咱们需求先判别一下用户设备是否有设置锁屏暗码:
private fun checkDeviceHasLockPwd(): Boolean {
val keyguardManager = getSystemService(KEYGUARD_SERVICE) as KeyguardManager
return keyguardManager.isKeyguardSecure
}
关于判别是否设置了锁屏暗码,这儿为了便利,是一致运用了 KeyguardManager 来进行判别,不然的话还需求根据 Android 版别进行判别,稍微麻烦了一点点。
下面咱们来写弹锁屏暗码验证的代码,xml 布局这儿不贴代码了,只是简略的界说了一个 Button 进行点击:
class VerifyActivity : AppCompatActivity() {
private val mBinding by lazy { ActivityVerifyBinding.inflate(layoutInflater) }
private lateinit var mKeyguardManager: KeyguardManager
private lateinit var mScreenLockResultLauncher: ActivityResultLauncher<Intent>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(mBinding.root)
mKeyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
initListener()
}
private fun initListener() {
mBinding.btnScreenLockAuth.setOnClickListener {
// 根据Android版别判别运用的方法
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
showDeviceLockVerify()
} else {
showScreenLockPwd()
}
}
// 因为startActivityForResult已弃用,所以改成registerForActivityResult方法来注册锁屏输入成果的回调监听
mScreenLockResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
Toast.makeText(this, "锁屏暗码验证成功", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "锁屏暗码验证失败", Toast.LENGTH_SHORT).show()
}
}
}
/**
* 跳转锁屏暗码校验页面
*/
private fun showScreenLockPwd() {
val intent = mKeyguardManager.createConfirmDeviceCredentialIntent("锁屏暗码", "请输入锁屏暗码验证您的身份")
if (intent != null) {
// 打开锁屏暗码验证页面
mScreenLockResultLauncher.launch(intent)
} else {
Toast.makeText(this, "当前设备暂未设置锁屏暗码", Toast.LENGTH_SHORT).show()
}
}
/**
* 跳转锁屏暗码验证页面(Android 10 以上调用)
*/
private fun showDeviceLockVerify() {
val executor = ContextCompat.getMainExecutor(this)
// 创立biometricPrompt以接纳成果的回调
val biometricPrompt = BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
Toast.makeText(this@VerifyActivity, "锁屏暗码验证成功", Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
// 这儿的判别是因为当用户点击撤销按钮的时分,不需求提示,其余的验证失败都需求提示
if (errorCode != BiometricPrompt.ERROR_NEGATIVE_BUTTON && errString.toString().isNotEmpty()) {
Toast.makeText(this@VerifyActivity, errString.toString(), Toast.LENGTH_SHORT).show()
}
}
})
// 创立锁屏暗码输入的弹框以及需求显示的文字
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
.setTitle("锁屏暗码")
.setConfirmationRequired(true)
.setSubtitle("请输入锁屏暗码验证您的身份")
.build()
// 发起验证
biometricPrompt.authenticate(promptInfo)
}
}
上面的注释都有标注得很清楚,首要便是 KeyguardManager
以及 Biometric 库中 BiometricPrompt
的运用,代码运转完之后的截图如下:

因为输入暗码涉及到灵敏信息,手机制止截屏,所以只能粗糙的拍下来了….
生物辨认
生物辨认包括指纹辨认以及面庞辨认,但是因为这个库对国产手机遍及都无法弹出面庞辨认,现在暂时只发现三星手机还有部分荣耀手机是支撑面庞辨认的,所以这儿没有把面庞辨认考虑进去,但是写法都是一样的不需求修正代码。
先来判别一下用户的设备硬件是否支撑生物辨认以及是否现已设置了指纹/面庞:
private fun checkDeviceHasFingerAuth(): Boolean {
val biometricManager = BiometricManager.from(this)
return biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK)
== BiometricManager.BIOMETRIC_SUCCESS
}
在上述的锁屏暗码验证的代码基础上新增代码如下:
private fun initListener() {
....
mBinding.btnFingerAuth.setOnClickListener {
showFingerVerify()
}
}
/**
* 跳转指纹辨认验证页面
*/
private fun showFingerVerify() {
val executor = ContextCompat.getMainExecutor(this)
val biometricPrompt = BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
Toast.makeText(this@VerifyActivity, "指纹验证成功", Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
if (errorCode != BiometricPrompt.ERROR_NEGATIVE_BUTTON && errString.toString().isNotEmpty()) {
Toast.makeText(this@VerifyActivity, errString.toString(), Toast.LENGTH_SHORT).show()
}
}
})
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK)
.setTitle("指纹辨认")
.setConfirmationRequired(true)
.setSubtitle("请运用您的指纹进行辨认")
.setNegativeButtonText("撤销")
.build()
biometricPrompt.authenticate(promptInfo)
}
这部分的调用跟上述的锁屏暗码调用的写法是基本一致的,差异只要文案以及 PromptInfo
中新增了 setNegativeButtonText("撤销")
用于撤销辨认,而在锁屏暗码验证的时分不需求这句代码是因为锁屏暗码验证的弹框中现已自带了撤销按钮。
代码运转完之后的截图如下:

这是只要指纹辨认的弹窗,假如是三星手机的话,还会弹出指纹以及面庞辨认的弹窗让用户自行挑选验证方法:

总结
写这篇文章首要是为了下次再运用的时分能够直接搬运而已,溜了溜了~