Android 10设备生物识别认证后Fragment提交崩溃问题求助
问题分析与修复方案
问题场景
使用以下生物识别验证代码,在多数设备上可正常跳转至下一个Fragment,但部分Android 10设备出现崩溃,错误信息:
Can not perform this action after onSaveInstanceState
原代码
val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric authentication") .setSubtitle("Verify using your biometric credential") .setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG or BiometricManager.Authenticators.DEVICE_CREDENTIAL or BiometricManager.Authenticators.BIOMETRIC_WEAK) .setConfirmationRequired(false) .build() val biometricPrompt = BiometricPrompt(this@Fragment, ContextCompat.getMainExecutor(requireActivity()), object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) goToNextScreen() // 提交Fragment事务跳转 } override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) Toast.makeText(context, errString, Toast.LENGTH_SHORT).show() } override fun onAuthenticationFailed() { Toast.makeText(context,"failed to verify", Toast.LENGTH_SHORT).show() super.onAuthenticationFailed() } }) biometricPrompt.authenticate(promptInfo)
崩溃原因
Android 10的部分设备中,BiometricPrompt弹窗显示时,系统可能会触发Activity的onSaveInstanceState方法(比如系统回收后台Activity资源、弹窗导致Activity进入后台状态)。而生物识别成功的回调,可能在Activity已经完成状态保存但尚未恢复到活跃状态时执行。此时提交Fragment事务,会触发系统抛出异常——Android禁止在onSaveInstanceState之后执行会改变界面状态的事务,防止状态丢失。
修复方案
方案1:使用commitAllowingStateLoss()替代commit()
修改goToNextScreen()中的Fragment提交逻辑,将commit()替换为commitAllowingStateLoss()。这个方法允许在状态保存后提交事务,虽然存在极端情况下状态丢失的可能,但在生物识别这种用户主动触发的跳转场景中,该风险可接受。
示例:
fun goToNextScreen() { val fragment = NextFragment() parentFragmentManager.beginTransaction() .replace(R.id.container, fragment) .addToBackStack(null) .commitAllowingStateLoss() // 替换原有的commit() }
方案2:检查组件状态后执行跳转
在回调中先判断Fragment和Activity的状态,确保处于可操作状态时再执行跳转:
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) // 检查Fragment是否已添加、Activity未销毁且未结束 if (isAdded && requireActivity().isFinishing.not() && requireActivity().isDestroyed.not()) { goToNextScreen() } }
方案3:延迟执行跳转逻辑
通过view.post()将跳转逻辑放到主线程消息队列的后续执行,等待Activity完成状态恢复后再处理:
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) view?.post { goToNextScreen() } }
内容的提问来源于stack exchange,提问作者Divesh
相关产品推荐
相关产品推荐

