Search code examples
androiddagger-hiltandroid-credential-manager

CredentialManager injected with Hilt throws "Failed to launch the selector UI"


I'm having trouble configuring a CredentialManager module through Hilt. In some devices (particularly a Redmi Note 9), when requesting a Google Sign-In the Credential Manager throws "Failed to launch the selector UI. Hint: ensure the 'context' parameter is an Activity-based context."

I'm suspecting that the problem lies on Hilt injecting an @ApplicationContext instead of an Activity-based Context, in order to instantiate the CredentialManager, but i currently don't know how to fix it

Another observation is that in some other devices (like a Galaxy S23), that error doesn't happen and the Sig-In UI appears normally

my authentication starts at a ViewModel with an AuthService injected into it:

@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"
                                    )
                                )
                            }
                        )
                    }
            }
        }
    }
}

the authService signature is as follows (google login implmentation is just a very generic one found in tutorials):

class AuthService @Inject constructor(
    @ApplicationContext private val context: Context,
    private val usuariosService: UsuariosService
)

And this is its module:

@Module
@InstallIn(SingletonComponent::class)
object AuthModule {

    @Provides
    @Singleton
    fun provideAuthClient(@ApplicationContext context: Context, usuariosService: UsuariosService): AuthService =
        AuthService(context.applicationContext, usuariosService)
}

If i try to change authService context injection to @ActivityContext I get a lengthy Hilt error that says

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

Solution

  • In case anyone stumbles upon this, i've finally understood my mistake: turns out that, while my @ActivityContext injection into my AuthModule was OK, I was still trying to inject the module in ViewModel, which means it would indirectly hold a reference to the Activity, and thus Hilt wouldn't allow me to inject it.

    My somewhat ugly solution was to just inject my module into the Activity itself, since I have only one, and then pass the module as a reference down to other composables, and THEN finally pass it down to the ViewModel so it could make its things

    @AndroidEntryPoint
    class MainActivity : ComponentActivity() {
      @Inject lateinit  var authService: AuthService
      // ....
      AuthScreen(authService = authService, ...)
    }