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

使用Hilt注入CredentialManager抛出“Failed to launch the selector UI”问题求助

问题分析与解决方案

问题根源

CredentialManager启动登录选择UI必须依赖Activity上下文,你的AuthService是单例(绑定在SingletonComponent),构造注入的是ApplicationContext,在部分严格遵循系统规范的设备(如Redmi Note 9)上会触发错误;而Galaxy S23这类设备的系统对Context兼容性更宽松,允许用ApplicationContext启动UI,所以无报错。

直接给AuthService注入@ActivityContext会报错,是因为SingletonComponent的生命周期覆盖整个应用,无法依赖仅存在于Activity生命周期内的ActivityContext实例。

修复方案

核心思路:不要在单例的AuthService构造中绑定ActivityContext,而是在调用登录方法时传入Activity实例,既避免生命周期不匹配的问题,又满足CredentialManager的上下文要求。

1. 调整AuthService的登录方法

修改googleSignIn方法,接收Activity作为参数,仅在需要启动UI时使用该Activity上下文:

class AuthService @Inject constructor(
    @ApplicationContext private val appContext: Context,
    private val usuariosService: UsuariosService
) {
    suspend fun googleSignIn(activity: Activity): Flow<Result<AuthResult>> {
        // 用Activity上下文实例化CredentialManager
        val credentialManager = CredentialManager.create(activity)
        
        // 后续的谷歌登录请求逻辑
        // 比如构建GetCredentialRequest、调用getCredential等
    }
}

2. 更新UI事件与ViewModel逻辑

让登录事件携带Activity实例,ViewModel调用AuthService时传入该实例:

  • 首先修改UiEvent密封类:
sealed class UiEvent {
    data class OnGoogleSignIn(val activity: Activity) : UiEvent()
    // 其他事件...
}
  • 然后更新ViewModel(无需再注入Context):
@HiltViewModel
class AuthViewModel @Inject constructor(
    private val authService: AuthService
) : ViewModel() {
    
    fun onEvent(uiEvent: UiEvent) {
        when (uiEvent) {
            is UiEvent.OnGoogleSignIn -> {
                viewModelScope.launch {
                    authService.googleSignIn(uiEvent.activity).collect { result ->
                        result.fold(
                            onSuccess = { authResult ->
                                _uiState.emit(AuthUiState.LoggedIn(authResult.user?.uid ?: ""))
                            },
                            onFailure = { exception ->
                                _uiState.emit(
                                    AuthUiState.Error(
                                        exception.message ?: "An error occurred"
                                    )
                                )
                            }
                        )
                    }
                }
            }
            // 其他事件处理...
        }
    }
}

3. 在UI层传递Activity实例

在你的登录Activity/Fragment中,调用ViewModel的onEvent时传入当前Activity:

// 示例:登录按钮点击事件
binding.btnGoogleSignIn.setOnClickListener {
    viewModel.onEvent(UiEvent.OnGoogleSignIn(this@AuthActivity))
}

注意事项

  • 避免ViewModel持有Activity强引用:通过viewModelScope启动协程,ViewModel销毁时协程会自动取消,不会导致内存泄漏。
  • 保留ApplicationContext:AuthService中仍保留ApplicationContext,用于无需UI交互的后台操作(如数据存储、API请求等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 10:23:25