当我尝试运行用于指纹身份验证的示例应用程序时,会引发以下异常。
我尝试过的设备是:
三星 S5 (安卓 6.0.1 API 23(
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: java.security.InvalidAlgorithmParameterException: java.lang.IllegalStateException: At least one fingerprint must be enrolled to create keys requiring user authentication for every use
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.security.keystore.AndroidKeyStoreKeyGeneratorSpi.engineInit(AndroidKeyStoreKeyGeneratorSpi.java:238)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.security.keystore.AndroidKeyStoreKeyGeneratorSpi$AES.engineInit(AndroidKeyStoreKeyGeneratorSpi.java:53)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at javax.crypto.KeyGenerator.init(KeyGenerator.java:189)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at com.netfinitymedia.notubeapp.authentication.VerificationActivity.generateKey(VerificationActivity.java:177)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at com.netfinitymedia.notubeapp.authentication.VerificationActivity.initialize(VerificationActivity.java:131)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at com.netfinitymedia.notubeapp.authentication.VerificationActivity.onCreate(VerificationActivity.java:63)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.app.Activity.performCreate(Activity.java:6876)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3206)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3349)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.app.ActivityThread.access$1100(ActivityThread.java:221)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.os.Looper.loop(Looper.java:158)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7224)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at java.lang.reflect.Method.invoke(Native Method)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: Caused by: java.lang.IllegalStateException: At least one fingerprint must be enrolled to create keys requiring user authentication for every use
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.security.keystore.KeymasterUtils.addUserAuthArgs(KeymasterUtils.java:115)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: at android.security.keystore.AndroidKeyStoreKeyGeneratorSpi.engineInit(AndroidKeyStoreKeyGeneratorSpi.java:234)
07-08 03:31:57.796 30558-30558/com.netfinitymedia.notubeapp W/System.err: ... 17 more
在尝试生成密钥之前,应使用指纹管理器检查指纹读取器是否存在以及应用是否有权使用它。
_fingerprintManager = (FingerprintManager) _context.getSystemService(FINGERPRINT_SERVICE);
public boolean fingerprintEnabled()
{
if (!_fingerprintManager.isHardwareDetected())
{
// Device doesn't support fingerprint authentication
return false;
}
else if (ActivityCompat.checkSelfPermission(_context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED)
{
return false;
}
else if (!_keyguardManager.isKeyguardSecure())
{
return false;
}
else if (!_fingerprintManager.hasEnrolledFingerprints())
{
// User hasn't enrolled any fingerprints to authenticate with
return false;
}
else
{
// Everything is ready for fingerprint authentication
return true;
}
}
正如文档所说,现在有了BiometricManager,我们可以使用canAuthenticate函数来检查身份验证器是否满足给定的要求。小心身份验证类型的组合!
val biometricManager = BiometricManager.from(this)
when (biometricManager.canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL))
这更像是一种解决方法。我希望它能帮助你和外面的其他人:
Timber.d("checkForBiometrics started")
val fingerprintManagerCompat = FingerprintManagerCompat.from(activity!!)
val pm = context!!.packageManager
val canAuthenticate: Boolean
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val hasFingerprint = pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
val hasFace = pm.hasSystemFeature(PackageManager.FEATURE_FACE)
val hasIris = pm.hasSystemFeature(PackageManager.FEATURE_IRIS)
if(hasFingerprint && hasFace || hasFingerprint && hasIris) {
Timber.d("checkForBiometrics has fingerprint and has face or iris")
canAuthenticate = fingerprintManagerCompat.hasEnrolledFingerprints()
} else if(hasFace || hasFingerprint) {
Timber.d("checkForBiometrics has only face or only fingerprint")
canAuthenticate = Biometric(activity!!).isAvailable()
}
else {
canAuthenticate = false
}
} else {
canAuthenticate = false
}
return canAuthenticate
如果设备具有更多生物识别选项,这将仅接受指纹身份验证。