In this blog we will briefly focus on two aspects of upgrading to Android 12:
- Splash screen migration or implementation
- Back navigation with navigation components
When upgrading to Android 12, you’ll want to update your splash screen implementation, or create a new one. If not, your app will either end up with two different splash screens – the first generated by Android, then followed by yours, or Android’s default splash screen will override your implementation completely.
To update this according to the latest recommendations, you should implement the SplashScreen API. Basically you will need to update your Gradle dependencies by adding:
Then you need to create a new custom scheme and install it in Activity’s onCreate() method by calling installSplashScreen() before calling setContentView(). You do not need individual splash screen activity; styling your main one is fine.
Here is an example of themes.xml applied to an app’s launch activity. Notice postSplashScreenTheme, which will apply a theme to your activity after the splash screen is gone:
<resources xmlns:tools="http://schemas.android.com/tools"> <style name="Theme.MigrationTest" parent="Theme.SplashScreen"> … <!-- Splash screen settings --> <item name="windowSplashScreenBackground">@color/white</item> <item name="windowSplashScreenAnimatedIcon">@drawable/splash_screen</item> <item name="postSplashScreenTheme">@style/Theme.MaterialComponents.DayNight.NoActionBar</item> </style> </resources>
Back navigation update
Android 12 does not kill your activity on back press by default anymore, instead moving the activity to the background. This should mean better performance for users when resuming these apps. If your apps currently override onBackPressed() and finish their activity inside this method, you should revisit your implementation and make sure to leave this in place only where necessary (for example for user-blocked screens, etc).
To define proper navigation, you should update your navigation graph with a back stack configuration.
Let’s assume you have a login fragment, main fragment and profile fragment. Once a user successfully logs into the app, you don’t want him to be able to get back to the login fragment by pressing the back button.
So what you should do is create an action within your navigation graph, which would navigate the user outside of the app if he tries to return to the login screen by pressing the back button. To do this, you need to specify behavior for the back stack in the navigation graph XML.
Basically, you will need to do two things –
The first is to specify app:popUpTo=”@+id/fragmentLogin” and app:popUpToInclusive=”true” settings. In this case, popUpTo can either be @+id/fragmentLogin or @+id/nav_graph. This tells the navigation system that on a back button press, the navigation component will navigate the user back to the destination defined in popUpTo. In addition, app:popUpToInclusive=”true” also removes the LoginFragment destination from the back stack, resulting in the user leaving the app as intended. If you were to keep it “false” it would navigate the user back to LoginFragment, and keep the app open.
The second is specifying launchSingleTop settings, which tells navigation to launch this as a single top and not to create a new instance every time the user navigates to the destination by a specified action. This is handy, for example, for fragments with a bottom navigation bar.
Here is an example of the above-mentioned navigation graph:
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph" app:startDestination="@id/fragmentLogin"> <fragment android:id="@+id/fragmentLogin" android:name="com.backnav.LoginFragment"> <action android:id="@+id/action_fragmentLogin_to_fragmenMain" app:destination="@id/fragmenMain" app:popUpTo="@+id/nav_graph" app:popUpToInclusive="true" app:launchSingleTop="true"/> </fragment> <fragment android:id="@+id/fragmenMain" android:name=" com.backnav.MainFragment"> <action android:id="@+id/action_fragmenMain_to_fragmentProfile" app:destination="@id/fragmentProfile" /> </fragment> <fragment android:id="@+id/fragmentProfile" android:name="com.backnav.ProfileFragment" /> </navigation>
If your app utilizes Toolbar you have to make sure it is set properly with the Navigation library. One thing to keep an eye out for is to ensure you list your top level destination IDs when creating AppBarConfiguration.
So, your Activity’s onCreate() method could look like this:
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment navController = navHostFragment.navController appBarConfiguration = AppBarConfiguration(topLevelDestinationIds = setOf(R.id.fragmenMain, R.id.fragmentLogin), fallbackOnNavigateUpListener = ::onSupportNavigateUp) findViewById<Toolbar>(R.id.toolbar) .setupWithNavController(navController, appBarConfiguration)
One would assume the library could do its job and deduce these top-level IDs from the navigation graph itself, but for now you have to add them manually.
Want to know more? Here are a selection of useful links with more detail about splash screen and navigation implementation and general info about migration to Android 12:
- Sample project can be downloaded here:
Curious about how it works with logging in Android? See a previous blog post on this topic.