运用指纹
说明 : 指纹解锁在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: 体系主张为0
arg3: 取消指纹验证 手动关闭验证 能够调用该参数的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方针
//生成Cipher
private 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)
}
//生成一个key
private 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地址