Jetpack Compose is Android’s modern toolkit for building native UI. It simplifies and accelerates UI development on Android. In this tutorial, we’re going to integrate Google sign-in with our app.
This tutorial assumes that you’ve already set up google credentials ( https://console.cloud.google.com/apis/credentials ) in the Google Cloud Platform. We’ll mainly focus on the android part of google sign in integration. (Note: You can easily generate SHA1 for your app with gradlew signingReport command in your IDE, which is required in Google console.)
We’ll start by creating a utility method that will provide GoogleSignInClient
fun getGoogleSignInClient(context: Context): GoogleSignInClient { val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(context.getString(R.string.backend_client_id)) // Request id token if you intend to verify google user from your backend server .requestEmail() .build() return GoogleSignIn.getClient(context, signInOptions) }
Next, we’ll create a Contract for ActivtyResultAPI which will get the sign-in result from Google prompt.
class AuthResultContract : ActivityResultContract<Int, Task<GoogleSignInAccount>?>() { override fun createIntent(context: Context, input: Int?): Intent = getGoogleSignInClient(context).signInIntent.putExtra("input", input) override fun parseResult(resultCode: Int, intent: Intent?): Task<GoogleSignInAccount>? { return when (resultCode) { Activity.RESULT_OK -> GoogleSignIn.getSignedInAccountFromIntent(intent) else -> null } } }
Now, let’s create a composable for the sign in button.
@ExperimentalMaterialApi @Composable fun SignInButton( text: String, loadingText: String = "Signing in...", icon: Painter, isLoading: Boolean = false, shape: Shape = Shapes.medium, borderColor: Color = Color.LightGray, backgroundColor: Color = MaterialTheme.colors.surface, progressIndicatorColor: Color = MaterialTheme.colors.primary, onClick: () -> Unit ) { Surface( modifier = Modifier.clickable( enabled = !isLoading, onClick = onClick ), shape = shape, border = BorderStroke(width = 1.dp, color = borderColor), color = backgroundColor ) { Row( modifier = Modifier .padding( start = 12.dp, end = 16.dp, top = 12.dp, bottom = 12.dp ), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { Icon( painter = icon, contentDescription = "SignInButton", tint = Color.Unspecified ) Spacer(modifier = Modifier.width(8.dp)) Text(text = if (isLoading) loadingText else text) if (isLoading) { Spacer(modifier = Modifier.width(16.dp)) CircularProgressIndicator( modifier = Modifier .height(16.dp) .width(16.dp), strokeWidth = 2.dp, color = progressIndicatorColor ) } } } }
which will create a sign-in button as below

Now, we’ll create AuthView that contains a sign-in button and error text to display errors that occurred during the sign-in process (if any).
@ExperimentalMaterialApi @Composable fun AuthView( errorText: String?, onClick: () -> Unit ) { var isLoading by remember { mutableStateOf(false) } Scaffold { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { SignInButton( text = "Sign in with Google", loadingText = "Signing in...", isLoading = isLoading, icon = painterResource(id = R.drawable.ic_google_logo), onClick = { isLoading = true onClick() } ) errorText?.let { isLoading = false Spacer(modifier = Modifier.height(30.dp)) Text(text = it) } } } }
Finally, we’ll create AuthScreen that will launch the google sign in prompt upon clicking on sign in button and navigating to HomeScreen if sign-in is successful, or show an error if it occurs.
@ExperimentalAnimationApi @ExperimentalFoundationApi @ExperimentalCoroutinesApi @ExperimentalMaterialApi @Composable fun AuthScreen( authViewModel: AuthViewModel ) { val coroutineScope = rememberCoroutineScope() var text by remember { mutableStateOf<String?>(null) } val user by remember(authViewModel) { authViewModel.user }.collectAsState() val signInRequestCode = 1 val authResultLauncher = rememberLauncherForActivityResult(contract = AuthResultContract()) { task -> try { val account = task?.getResult(ApiException::class.java) if (account == null) { text = "Google sign in failed" } else { coroutineScope.launch { authViewModel.signIn( email = account.email, displayName = account.displayName, ) } } } catch (e: ApiException) { text = "Google sign in failed" } } AuthView( errorText = text, onClick = { text = null authResultLauncher.launch(signInRequestCode) } ) user?.let { HomeScreen(user = it) } }
That’s it. The app is ready to handle Google sign-in with compose UI. You can launch and test the Google sign-in flow.
#Adding some animations
As you’ll notice, when you click on the sign-in button, a circular loading bar appears directly without animation, which looks boring. We can add smooth animations to make it eye-catching.
@Composable fun SignInButton( ... ) { Surface( ... ) { Row( modifier = Modifier .animateContentSize( animationSpec = tween( durationMillis = 300, easing = LinearOutSlowInEasing ) ), ... ) { ... } } }
You can find the complete code on GitHub.
https://github.com/hadiyarajesh/ComposeGoogleSignIn



