Prerequisite
Depedencies
dependencies {
// Import the BoM for the Firebase platform
implementation platform('com.google.firebase:firebase-bom:29.0.0')
// Declare the dependency for the Firebase Authentication library
// When using the BoM, you don't specify versions in Firebase library dependencies
implementation 'com.google.firebase:firebase-auth-ktx'
// Also declare the dependency for the Google Play services library and specify its version
implementation 'com.google.android.gms:play-services-auth:19.2.0'
}
Also, remember setup your app's SHA-1 fingerprint at Firebase Settings.
Enable Google Sign-In
at Auth
section of Firebase Console.
Code
Activity
class MainActivity : ComponentActivity() { private val auth: FirebaseAuth = Firebase.auth private lateinit var googleSignInClient: GoogleSignInClient private lateinit var authResultLauncher: ActivityResultLauncher<Intent> private val viewModel: MainViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) auth.addAuthStateListener { auth -> Timber.d("addAuthStateListener: ${auth.currentUser}") viewModel.setCurrentUser(auth.currentUser) } // R.string.default_web_client_id is created automatically as per google-services.json, // though sometimes the IDE might not recognize it val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(getString(R.string.default_web_client_id)) .requestEmail() .build() googleSignInClient = GoogleSignIn.getClient(this, gso) authResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> // if (result.resultCode == Activity.RESULT_OK) { // There are no request codes val data: Intent? = result.data val task = GoogleSignIn.getSignedInAccountFromIntent(data) try { // Google Sign In was successful, authenticate with Firebase val account = task.getResult(ApiException::class.java)!! Timber.d("firebaseAuthWithGoogle:" + account.id) firebaseAuthWithGoogle(account.idToken!!) } catch (e: ApiException) { // Google Sign In failed, update UI appropriately Timber.w(e, "Google sign in failed") } // } } setContent { JourneyTheme { UserProfileScreen( viewModel = viewModel, onSignIn = { signIn() }, onSignOut = { auth.signOut() } ) } } } fun signIn() { val signInIntent = googleSignInClient.signInIntent // startActivityForResult(signInIntent, RC_SIGN_IN) authResultLauncher.launch(signInIntent) } private fun firebaseAuthWithGoogle(idToken: String) { val credential = GoogleAuthProvider.getCredential(idToken, null) auth.signInWithCredential(credential) .addOnCompleteListener(this) { task -> if (task.isSuccessful) { // Sign in success, update UI with the signed-in user's information Timber.d("signInWithCredential:success") // val user = auth.currentUser // updateUI(user) } else { // If sign in fails, display a message to the user. Timber.w(task.exception, "signInWithCredential:failure") // updateUI(null) } } } }
Composable
@Composablefun UserProfileScreen(viewModel: MainViewModel, onSignIn: () -> Unit, onSignOut: () -> Unit) { val currentUser = viewModel.currentUser Column(modifier = Modifier.padding(16.dp)) { if (currentUser == null) { Button(onClick = { onSignIn() }){ Text(text = "Sign in with Google") } } else { Text(text = "Welcome, ${currentUser.displayName}") Button(onClick = { onSignOut() } ) { Text(text = "Sign out") } } }}
ViewModel
class MainViewModel : ViewModel() { var currentUser by mutableStateOf<FirebaseUser?>(null) private set @JvmName("assignCurrentUser") fun setCurrentUser(user: FirebaseUser?) { currentUser = user }}
Potential Errors
Requests to this API firebaseinstallations.googleapis.com method google.firebase.installations.v1.FirebaseInstallationsService.CreateInstallation are blocked.
If you enable restrictions for your API, goto Google Cloud Console -> Credentials, Edit API key -> API restrictions
and enable Firebase Installations API
.
com.google.firebase.FirebaseException: An internal error has occurred. [ Requests to this API identitytoolkit method google.cloud.identitytoolkit.v1.AuthenticationService.SignInWithIdp are blocked. ]
Enable Identity Toolkit API
to your API restrictions.
Requests to this API securetoken.googleapis.com method google.identity.securetoken.v1.SecureToken.GrantToken are blocked.
Enable Token Service API
to your API restrictions.
References: