Table of Contents
Jetpack Compose is a modern toolkit for building native Android user interfaces. Firebase Authentication provides backend services for easy and secure user sign-in. Combining these tools allows developers to create seamless authentication flows within their Compose apps. This guide covers the essential steps to integrate Firebase Authentication into your Jetpack Compose project.
Setting Up Firebase in Your Android Project
Start by creating a Firebase project in the Firebase Console. Link your Android app by registering it with your project, then download the google-services.json file and add it to your app module directory. Ensure your project-level build.gradle includes the Google services classpath and apply the plugin in your app-level build.gradle.
In your app's build.gradle, add the Firebase SDK dependencies:
implementation 'com.google.firebase:firebase-auth-ktx'
Sync your project to download dependencies.
Implementing Firebase Authentication
Create a singleton or a class to manage FirebaseAuth instance:
val auth: FirebaseAuth = FirebaseAuth.getInstance()
Sign-In Function
Implement functions to handle user sign-in, sign-up, and sign-out:
fun signIn(email: String, password: String, onResult: (Boolean, String?) -> Unit) {
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
onResult(true, null)
} else {
onResult(false, task.exception?.message)
}
}
}
Creating the Compose UI
Design your login screen with Compose components, including text fields and buttons:
@Composable
fun LoginScreen(
onLoginSuccess: () -> Unit,
viewModel: AuthViewModel = viewModel()
) {
val email = remember { mutableStateOf("") }
val password = remember { mutableStateOf("") }
val context = LocalContext.current
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center
) {
TextField(
value = email.value,
onValueChange = { email.value = it },
label = { Text("Email") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
TextField(
value = password.value,
onValueChange = { password.value = it },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation(),
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
viewModel.signIn(email.value, password.value) { success, message ->
if (success) {
onLoginSuccess()
} else {
Toast.makeText(context, message ?: "Login failed", Toast.LENGTH_SHORT).show()
}
}
},
modifier = Modifier.fillMaxWidth()
) {
Text("Login")
}
}
}
Connecting ViewModel with Firebase
Create a ViewModel to handle authentication logic and expose state to the UI:
class AuthViewModel : ViewModel() {
private val auth = FirebaseAuth.getInstance()
fun signIn(email: String, password: String, onResult: (Boolean, String?) -> Unit) {
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
onResult(true, null)
} else {
onResult(false, task.exception?.message)
}
}
}
}
Handling Authentication State
Observe the current user to update UI accordingly:
@Composable
fun MainScreen() {
val auth = FirebaseAuth.getInstance()
val user = auth.currentUser
if (user != null) {
// User is signed in
WelcomeScreen()
} else {
// User is not signed in
LoginScreen(onLoginSuccess = { /* navigate to main content */ })
}
}
Conclusion
Integrating Firebase Authentication with Jetpack Compose involves setting up Firebase, implementing authentication logic, and designing reactive UI components. This combination enables secure and seamless user login experiences in modern Android applications. Remember to handle user state properly and provide feedback to ensure a smooth user experience.