Jetpack Compose is a modern toolkit for building native Android user interfaces. Implementing authentication in your app is essential for securing user data and providing personalized experiences. This step-by-step guide will walk you through setting up authentication in your Jetpack Compose Android app.
Prerequisites
- Android Studio installed (Arctic Fox or later)
- Basic knowledge of Kotlin and Jetpack Compose
- Google Firebase account
- Android project set up with Jetpack Compose
Step 1: Add Firebase to Your Project
First, connect your Android app to Firebase. Go to the Firebase Console and create a new project or select an existing one. Follow the instructions to add your Android app, download the google-services.json file, and place it in your app's app/ directory.
Next, add the Firebase SDK to your project's build.gradle files:
// Project-level build.gradle
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.3.15'
}
}
// App-level build.gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.gms.google-services'
}
dependencies {
implementation 'com.google.firebase:firebase-auth-ktx:21.1.0'
}
Step 2: Set Up Firebase Authentication
In the Firebase Console, navigate to the Authentication section. Enable the sign-in methods you want to support, such as Email/Password, Google, Facebook, etc. For this guide, we'll focus on Email/Password authentication.
Step 3: Create Authentication UI in Jetpack Compose
Design simple login and registration screens using Jetpack Compose. Here's an example of a login screen:
@Composable
fun LoginScreen(
onLoginSuccess: () -> Unit,
onNavigateToRegister: () -> Unit
) {
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var errorMessage by remember { mutableStateOf(null) }
val auth = FirebaseAuth.getInstance()
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center
) {
Text(text = "Login", style = MaterialTheme.typography.h4)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = email,
onValueChange = { email = it },
label = { Text("Email") }
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation()
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
onLoginSuccess()
} else {
errorMessage = task.exception?.message
}
}
},
modifier = Modifier.fillMaxWidth()
) {
Text("Login")
}
errorMessage?.let {
Text(text = it, color = Color.Red)
}
Spacer(modifier = Modifier.height(8.dp))
TextButton(onClick = onNavigateToRegister) {
Text("Create an account")
}
}
}
Step 4: Handle Authentication State
Implement a way to observe the user's authentication state and navigate accordingly. For example:
@Composable
fun AuthNavigation() {
val auth = FirebaseAuth.getInstance()
val user by remember { mutableStateOf(auth.currentUser) }
LaunchedEffect(Unit) {
auth.addAuthStateListener { firebaseAuth ->
// Update UI based on auth state
}
}
if (auth.currentUser != null) {
// Show main app screen
MainScreen()
} else {
// Show login screen
LoginScreen(
onLoginSuccess = { /* handle success */ },
onNavigateToRegister = { /* navigate to registration */ }
)
}
}
Step 5: Register New Users
Create a registration screen similar to the login screen, using createUserWithEmailAndPassword method:
@Composable
fun RegisterScreen(
onRegisterSuccess: () -> Unit,
onNavigateToLogin: () -> Unit
) {
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var errorMessage by remember { mutableStateOf(null) }
val auth = FirebaseAuth.getInstance()
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center
) {
Text(text = "Register", style = MaterialTheme.typography.h4)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = email,
onValueChange = { email = it },
label = { Text("Email") }
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation()
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
onRegisterSuccess()
} else {
errorMessage = task.exception?.message
}
}
},
modifier = Modifier.fillMaxWidth()
) {
Text("Register")
}
errorMessage?.let {
Text(text = it, color = Color.Red)
}
Spacer(modifier = Modifier.height(8.dp))
TextButton(onClick = onNavigateToLogin) {
Text("Already have an account? Login")
}
}
}
Conclusion
Integrating Firebase Authentication with Jetpack Compose simplifies managing user sign-in and registration. By following this guide, you can add secure authentication features to your Android apps, enhancing user experience and security.