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

使用Hilt注入Activity实现BiometricPrompt遇异常的解决方案咨询

解决Hilt注入Activity显示BiometricPrompt的异常问题

你的核心问题是将绑定Activity生命周期的BiometricPromptManager声明为了Singleton。SingletonComponent的依赖在Application初始化阶段就会被创建,此时注入的Activity实例还未完成与Application的绑定(未走到onCreate生命周期),而BiometricPrompt.authenticate()内部会依赖Activity的ViewModelStore,因此抛出IllegalStateException。

以下是几个符合架构规范的最佳解决方案:

方案1:使用Activity-scoped的依赖注入(推荐)

BiometricPrompt本身与Activity强绑定,生命周期完全依赖Activity,因此不应该做成单例。修改Hilt Module的作用域为ActivityComponent,确保每次Activity创建时生成对应的BiometricPromptManager实例,且实例初始化时Activity已完成绑定:

@Module
@InstallIn(ActivityComponent::class) // 改为Activity作用域
object BiometricModule { 
    @Provides
    // 去掉@Singleton,默认是Activity-scoped
    fun provideBiometricPromptManager(
        activity: AppCompatActivity // 注入通用的AppCompatActivity而非具体MainActivity
    ): BiometricPromptManager {
        return BiometricPromptManagerImpl(activity)
    }
}

在需要使用的组件(如ViewModel)中直接注入BiometricPromptManager即可,此时获取的实例与当前Activity绑定,且Activity已处于可用状态。

方案2:通过Provider延迟获取Activity实例

如果必须在非Activity-scoped的类中使用(如Singleton的Repository),可以通过Provider<AppCompatActivity>延迟获取Activity实例,确保调用时Activity已完成初始化:

class BiometricPromptManagerImpl(
    private val activityProvider: Provider<AppCompatActivity> // 使用Provider延迟获取
) : BiometricPromptManager {

    fun showBiometricPrompt(...) {
        val activity = activityProvider.get()
        check(activity.isAttachedToApplication) { "Activity未绑定Application" }
        val prompt = BiometricPrompt(activity, ...)
        prompt.authenticate(...)
    }
}

对应的Module:

@Module
@InstallIn(SingletonComponent::class)
object BiometricModule { 
    @Provides
    @Singleton
    fun provideBiometricPromptManager(
        activityProvider: Provider<AppCompatActivity>
    ): BiometricPromptManager {
        return BiometricPromptManagerImpl(activityProvider)
    }
}

注意:这种方式需要确保调用showBiometricPrompt时存在活跃的Activity实例,适合UI触发的场景。

方案3:Compose项目使用Biometric Compose库(无侵入式)

如果你的项目使用Jetpack Compose,可直接使用androidx.biometric:biometric-compose库,无需直接持有Activity实例,完全符合Compose架构与整洁分层原则:

  1. 添加依赖:
implementation "androidx.biometric:biometric-compose:1.0.0-alpha06"
  1. 在Composable中使用:
@Composable
fun BiometricAuthScreen(onAuthSuccess: () -> Unit) {
    val biometricPrompt = rememberBiometricPrompt(
        onAuthError = { errorCode, errString -> /* 处理错误 */ },
        onAuthFailed = { /* 处理失败 */ },
        onAuthSucceeded = { 
            onAuthSuccess()
        }
    )

    Button(onClick = {
        biometricPrompt.authenticate(PromptInfo.Builder()
            .setTitle("身份验证")
            .setSubtitle("请验证指纹")
            .build())
    }) {
        Text("验证指纹")
    }
}

这种方式下,业务层只需定义回调逻辑,UI层负责Biometric的显示,完全隔离了分层依赖。

内容的提问来源于stack exchange,提问作者Thomas Constantin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:05:07