Challenge 3: A Remote Config Feature Flag — Solution suspend fun isNewDashboardEnabled(): Boolean { val remoteConfig = Firebase.remoteConfig remoteConfig.setDefaultsAsync(mapOf("new_dashboard_enabled" to false)).await() remoteConfig.fetchAndActivate().await() return remoteConfig.getBoolean("new_dashboard_enabled") } // Sketch: using it in a composable // // @Composable // fun MainScreen() { // var showNewDashboard by remember { mutableStateOf(false) } // // LaunchedEffect(Unit) { // showNewDashboard = isNewDashboardEnabled() // } // // if (showNewDashboard) { // NewDashboardScreen() // } else { // OldDashboardScreen() // } // } // Advantage over shipping the new dashboard directly in a release build: // // With Remote Config, the choice of which dashboard a user sees is // controlled from the Firebase console, INSTANTLY, for an ALREADY- // INSTALLED user base — no new APK/AAB build, no Chapter 7 signing step, // no Play Console review wait, and critically, no dependency on users // actually updating their app (Chapter 7's point about users being able // to delay or decline updates). If NewDashboardScreen turns out to have // a serious bug, flipping "new_dashboard_enabled" back to false in the // Firebase console reverts every installed app to the old dashboard // within the next fetch cycle — a rollback measured in minutes, not the // hours-to-days a real Play Store release cycle requires per Chapter 7. // This is exactly the same "feature flag" advantage the web deployment // chapter (Node Course 3) described for canary rollouts, just applied to // a platform where the alternative (shipping a new build) is genuinely // much slower. Notes: - LaunchedEffect(Unit) is Compose's way to run a suspend function once when a composable enters composition — appropriate here since isNewDashboardEnabled() is itself a suspend function (it awaits a network fetch) and can't be called directly from a composable's synchronous body. - setDefaultsAsync(...) ensures getBoolean(...) has a sane fallback (false) even if the fetch hasn't completed yet or fails entirely — the app never ends up in an undefined state waiting indefinitely for a config value that might never arrive.