我在通过 Hilt 配置 CredentialManager 模块时遇到问题。在某些设备(特别是 Redmi Note 9)中,当请求 Google 登录时,凭据管理器会抛出“无法启动选择器 UI。提示:确保‘上下文’参数是基于活动的上下文。”
我怀疑问题在于 Hilt 注入 @ApplicationContext 而不是基于 Activity 的上下文,以便实例化 CredentialManager,但我目前不知道如何修复它
另一个观察结果是,在某些其他设备(例如 Galaxy S23)中,不会发生该错误,并且登录 UI 会正常显示
我的身份验证从 ViewModel 开始,并注入了 AuthService:
@HiltViewModel
class AuthViewModel @Inject constructor(
private val authService: AuthService,
@ApplicationContext private val context: Context
) : ViewModel() {
fun onEvent(uiEvent: UiEvent) {
when (uiEvent) {
// ....
is UiEvent.OnGoogleSignIn -> {
viewModelScope.launch {
val currentUser = authService.googleSignIn().collect { result ->
// Handle the result
result.fold(
onSuccess = { authResult ->
_uiState.emit(AuthUiState.LoggedIn(authResult.user?.uid ?: ""))
},
onFailure = { exception ->
_uiState.emit(
AuthUiState.Error(
exception.message ?: "An error occurred"
)
)
}
)
}
}
}
}
}
authService 签名如下(谷歌登录实现只是教程中的一个非常通用的实现):
class AuthService @Inject constructor(
@ApplicationContext private val context: Context,
private val usuariosService: UsuariosService
)
这是它的模块:
@Module
@InstallIn(SingletonComponent::class)
object AuthModule {
@Provides
@Singleton
fun provideAuthClient(@ApplicationContext context: Context, usuariosService: UsuariosService): AuthService =
AuthService(context.applicationContext, usuariosService)
}
如果我尝试将 authService 上下文注入更改为 @ActivityContext,我会收到一个冗长的 Hilt 错误,上面写着
error: [Dagger/MissingBinding] @dagger.hilt.android.qualifiers.ActivityContext android.content.Context cannot be provided without an @Provides-annotated method.
public abstract static class SingletonC implements HiltApplication_GeneratedInjector
万一有人偶然发现这一点,我终于明白了我的错误:事实证明,虽然我的 @ActivityContext 注入我的 AuthModule 没问题,但我仍在尝试将模块注入 ViewModel 中,这意味着它将间接保存引用到 Activity,因此 Hilt 不允许我注入它。
我有点丑陋的解决方案是将我的模块注入到 Activity 本身中,因为我只有一个,然后将该模块作为引用传递给其他可组合项,然后最后将其传递给 ViewModel,以便它可以制作它的东西
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject lateinit var authService: AuthService
// ....
AuthScreen(authService = authService, ...)
}