This guide helps you migrate from FirebaseUI Auth 9.x (View-based) to 10.x (Compose-based). Note that 10.x is a beta release.
FirebaseUI Auth 10.x is a complete rewrite built with Jetpack Compose and Material Design 3. The architecture has changed significantly from the View-based system to a modern, declarative UI framework.
- 9.x: Android Views, Activities, Fragments
- 10.x: Jetpack Compose, Composables
- 9.x: Builder pattern (
createSignInIntentBuilder()) - 10.x: Kotlin DSL (
authUIConfiguration {})
- 9.x:
IdpConfig.EmailBuilder().build() - 10.x:
AuthProvider.Email()
- 9.x: Activity-based with
startActivityForResult()andActivityResultLauncher - 10.x: Composable screens with direct callbacks OR
AuthFlowControllerfor Activity-based apps
- 9.x: XML theme resources (
R.style.AppTheme) - 10.x:
AuthUIThemewith Material 3 color schemes
- 9.x:
AuthStateListenercallbacks - 10.x: Reactive
Flow<AuthState>
Old (9.x):
dependencies {
implementation("com.firebaseui:firebase-ui-auth:9.1.1")
}New (10.x):
dependencies {
// FirebaseUI Auth
implementation("com.firebaseui:firebase-ui-auth:10.0.0-beta01")
// Required: Jetpack Compose
implementation(platform("androidx.compose:compose-bom:2024.01.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
}Old (9.x) - Activity-based:
public class SignInActivity extends AppCompatActivity {
private final ActivityResultLauncher<Intent> signInLauncher =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
IdpResponse response = IdpResponse.fromResultIntent(result.getData());
if (result.getResultCode() == RESULT_OK) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
// User signed in
} else {
// Sign in failed
}
}
);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signin);
Intent signInIntent = AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder().build(),
new AuthUI.IdpConfig.GoogleBuilder().build()
))
.setTheme(R.style.AppTheme)
.build();
signInLauncher.launch(signInIntent);
}
}New (10.x) - Compose-based:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
val configuration = authUIConfiguration {
providers = listOf(
AuthProvider.Email(),
AuthProvider.Google()
)
theme = AuthUITheme.fromMaterialTheme()
}
FirebaseAuthScreen(
configuration = configuration,
onSignInSuccess = { result ->
val user = result.user
// User signed in
},
onSignInFailure = { exception ->
// Sign in failed
},
onSignInCancelled = {
finish()
}
)
}
}
}
}Old (9.x):
List<AuthUI.IdpConfig> providers = Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder()
.setRequireName(true)
.build(),
new AuthUI.IdpConfig.GoogleBuilder()
.build(),
new AuthUI.IdpConfig.PhoneBuilder()
.build()
);New (10.x):
val configuration = authUIConfiguration {
providers = listOf(
AuthProvider.Email(
isDisplayNameRequired = true
),
AuthProvider.Google(
scopes = listOf("email"),
serverClientId = "YOUR_CLIENT_ID"
),
AuthProvider.Phone(
defaultCountryCode = "US"
)
)
}Old (9.x) - XML styles:
<style name="AppTheme" parent="FirebaseUI">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
</style>.setTheme(R.style.AppTheme)New (10.x) - Material 3:
val configuration = authUIConfiguration {
providers = listOf(AuthProvider.Email())
theme = AuthUITheme(
colorScheme = lightColorScheme(
primary = Color(0xFF6200EE),
onPrimary = Color.White,
secondary = Color(0xFF03DAC6)
)
)
}Or inherit from your app theme:
MyAppTheme {
val configuration = authUIConfiguration {
providers = listOf(AuthProvider.Email())
theme = AuthUITheme.fromMaterialTheme()
}
FirebaseAuthScreen(configuration = configuration, ...)
}Old (9.x):
AuthUI.getInstance()
.signOut(this)
.addOnCompleteListener(task -> {
// User signed out
});New (10.x):
lifecycleScope.launch {
FirebaseAuthUI.getInstance().signOut(context)
// User signed out
}Old (9.x):
AuthUI.getInstance()
.delete(this)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
// Account deleted
} else {
// Deletion failed
}
});New (10.x):
lifecycleScope.launch {
try {
FirebaseAuthUI.getInstance().delete(context)
// Account deleted
} catch (e: Exception) {
// Deletion failed
}
}Old (9.x):
FirebaseAuth.getInstance().addAuthStateListener(firebaseAuth -> {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
} else {
// User is signed out
}
});New (10.x):
@Composable
fun AuthGate() {
val authUI = remember { FirebaseAuthUI.getInstance() }
val authState by authUI.authStateFlow().collectAsState(initial = AuthState.Idle)
when (authState) {
is AuthState.Success -> {
// User is signed in
MainAppScreen()
}
else -> {
// Show authentication
FirebaseAuthScreen(...)
}
}
}Old (9.x):
new AuthUI.IdpConfig.EmailBuilder()
.setRequireName(true)
.setAllowNewAccounts(true)
.enableEmailLinkSignIn()
.setActionCodeSettings(actionCodeSettings)
.build()New (10.x):
AuthProvider.Email(
isDisplayNameRequired = true,
isNewAccountsAllowed = true,
isEmailLinkSignInEnabled = true,
emailLinkActionCodeSettings = actionCodeSettings {
url = "https://example.com/auth"
handleCodeInApp = true
setAndroidPackageName(packageName, true, null)
}
)Old (9.x):
new AuthUI.IdpConfig.GoogleBuilder()
.setScopes(Arrays.asList("email", "profile"))
.build()New (10.x):
AuthProvider.Google(
scopes = listOf("email", "profile"),
serverClientId = "YOUR_CLIENT_ID"
)Old (9.x):
new AuthUI.IdpConfig.PhoneBuilder()
.setDefaultNumber("US", "+1 123-456-7890")
.build()New (10.x):
AuthProvider.Phone(
defaultCountryCode = "US",
defaultNumber = "+11234567890"
)If you have an existing Activity-based app and want to keep using Activities:
New (10.x) - Low-Level API:
class AuthActivity : ComponentActivity() {
private lateinit var controller: AuthFlowController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val authUI = FirebaseAuthUI.getInstance()
val configuration = authUIConfiguration {
providers = listOf(AuthProvider.Email(), AuthProvider.Google())
}
controller = authUI.createAuthFlow(configuration)
lifecycleScope.launch {
val state = controller.start()
when (state) {
is AuthState.Success -> {
startActivity(Intent(this, MainActivity::class.java))
finish()
}
is AuthState.Error -> {
// Handle error
}
else -> {
// Handle other states
}
}
}
}
override fun onDestroy() {
super.onDestroy()
controller.dispose()
}
}Solution: Ensure you have the correct import:
import com.firebase.ui.auth.configuration.authUIConfigurationSolution: In 10.x, you no longer need ActivityResultLauncher. Use direct callbacks with FirebaseAuthScreen or AuthFlowController.
Solution: Use content slots for custom UI:
EmailAuthScreen(
configuration = emailConfig,
onSuccess = { /* ... */ },
onError = { /* ... */ },
onCancel = { /* ... */ }
) { state ->
// Your custom UI here
CustomSignInUI(state)
}Solution: Convert XML themes to Kotlin code using AuthUITheme:
val configuration = authUIConfiguration {
theme = AuthUITheme(
colorScheme = lightColorScheme(
primary = Color(0xFF6200EE),
// ... other colors
)
)
}- Build the app - Ensure it compiles without errors
- Test all auth flows - Sign in, sign up, password reset
- Test all providers - Email, Google, Phone, etc.
- Test sign out - Verify users can sign out
- Test account deletion - Verify accounts can be deleted
- Test error handling - Verify errors are handled gracefully
- Test theming - Verify UI matches your design
- Updated dependency to
firebase-ui-auth:10.0.0-beta01 - Migrated to Jetpack Compose
- Converted Activities to ComponentActivities with
setContent {} - Replaced
createSignInIntentBuilder()withauthUIConfiguration {} - Updated all provider configurations
- Converted XML themes to
AuthUITheme - Updated error handling from result codes to exceptions
- Removed
ActivityResultLaunchercode - Updated sign-out to use suspend functions
- Updated account deletion to use suspend functions
- Tested all authentication flows
- Tested on multiple Android versions