如何取消认证后FingerprintManager.AuthenticationCallback并解决FINGERPRINT_ERROR_LOCKOUT重试无响应问题
问题原因
1. 30秒后指纹无响应的核心原因
- 触发
FINGERPRINT_ERROR_LOCKOUT时,当前正在使用的AuthenticationCallback会话已经被系统标记为失效,即使锁定时间结束,系统也不会主动向旧的回调推送事件,必须重新发起认证请求才能激活指纹硬件监听 - 你当前代码中
authenticate方法的第二个参数传入了null,没有持有CancellationSignal实例,无法主动终止旧的认证会话,残留的会话会占用指纹硬件资源,导致新的认证请求无法正常生效 - 部分厂商ROM自定义了指纹锁定逻辑,锁定时长可能不等于标准的30秒,部分机型需要主动发起新的认证请求才会重置锁定状态,单纯等待后直接放置指纹不会触发任何响应
2. 取消AuthenticationCallback的方法
可以取消,需要通过CancellationSignal实现:每次发起认证时创建新的CancellationSignal实例传入authenticate方法,需要取消回调时调用该实例的cancel()方法,系统就会解绑对应回调,不再向其推送任何事件,同时释放指纹硬件资源。
可行解决方案
修改代码逻辑如下:
// 全局持有取消信号和回调引用 private CancellationSignal mCancellationSignal; private FingerprintManager.AuthenticationCallback mAuthenticationCallback; private void initFingerprintAuth() { FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE); // 先判断指纹硬件可用且已录入指纹,否则直接返回 if (!fingerprintManager.isHardwareDetected() || !fingerprintManager.hasEnrolledFingerprints()) { return; } mAuthenticationCallback = new FingerprintManager.AuthenticationCallback() { @Override public void onAuthenticationError(int errorCode, CharSequence errString) { super.onAuthenticationError(errorCode, errString); Log.w("ABC", "101 - " + errorCode + " - " + errString); // 先取消当前会话 if (mCancellationSignal != null && !mCancellationSignal.isCanceled()) { mCancellationSignal.cancel(); } // 处理锁定错误 if (errorCode == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) { // 延迟30秒后重新发起认证,可根据errString返回的实际等待时间调整时长 new Handler(Looper.getMainLooper()).postDelayed(() -> { // 重新发起认证前先判断指纹状态是否正常 if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) { startFingerprintAuth(fingerprintManager); } }, 30 * 1000); } } @Override public void onAuthenticationFailed() { super.onAuthenticationFailed(); Log.w("ABC", "102"); } @Override public void onAuthenticationHelp(int helpCode, CharSequence helpString) { super.onAuthenticationHelp(helpCode, helpString); Log.w("ABC", "103 - " + helpCode + " - " + helpString); } @Override public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { super.onAuthenticationSucceeded(result); Log.w("ABC", "104"); // 认证成功后取消会话释放资源 if (mCancellationSignal != null && !mCancellationSignal.isCanceled()) { mCancellationSignal.cancel(); } } }; startFingerprintAuth(fingerprintManager); } private void startFingerprintAuth(FingerprintManager fingerprintManager) { // 每次发起认证都创建新的取消信号 mCancellationSignal = new CancellationSignal(); fingerprintManager.authenticate(null, mCancellationSignal, 0, mAuthenticationCallback, null); }
额外说明:FingerprintManager在API 28及以上版本已被废弃,更高版本系统建议使用BiometricPrompt实现指纹认证,兼容性和稳定性更好,也无需单独处理厂商适配问题。
内容的提问来源于stack exchange,提问作者Taha Sami
相关产品推荐
相关产品推荐

