You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 00:13:11