The Android 12+ Splash Screen API

AndroidUXStartupMaterial Design
Share on LinkedIn

Android 12 made splash screens mandatory — every app shows one on launch whether you want it or not. If you don't configure it, users see a generic system splash with your launcher icon on a white or black background. The SplashScreen compat library lets you customize the icon, background color, and exit animation, and critically, it backports the behavior to API 23+. The old pattern of a dedicated SplashActivity with a 2-second delay is dead — it fights the system splash, doubles launch time, and Google explicitly discourages it. Configure the system splash properly and delete your splash Activity.

Setup

dependencies {
    implementation("androidx.core:core-splashscreen:1.0.1")
}

Apply the splash theme to your launcher Activity:

<!-- themes.xml -->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/splash_background</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
    <item name="windowSplashScreenAnimationDuration">1000</item>
    <item name="postSplashScreenTheme">@style/Theme.App</item>
</style>
<!-- AndroidManifest.xml -->
<activity
    android:name=".MainActivity"
    android:theme="@style/Theme.App.Starting"
    android:exported="true">
    <intent-filter>...</intent-filter>
</activity>

Install in Activity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen()
        super.onCreate(savedInstanceState)
        setContent { AppTheme { MainScreen() } }
    }
}

installSplashScreen() must be called before super.onCreate(). The splash dismisses automatically when the first frame draws.

Animated icon

Android 12 supports animated vector drawables as splash icons:

<!-- res/drawable/splash_icon.xml -->
<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_logo_static">
    <target android:name="path" android:animation="@anim/splash_path_anim"/>
</animated-vector>

Keep animations under 1000ms. The system enforces a maximum animation duration. Simple scale/fade works best — complex animations may not render on all devices.

Exit animation

Customize the transition from splash to app content:

override fun onCreate(savedInstanceState: Bundle?) {
    val splashScreen = installSplashScreen()
    super.onCreate(savedInstanceState)

    splashScreen.setOnExitAnimationListener { splashViewProvider ->
        val slideUp = ObjectAnimator.ofFloat(
            splashViewProvider.view, View.TRANSLATION_Y, 0f, -splashViewProvider.view.height.toFloat()
        ).apply {
            duration = 300
            interpolator = AnticipateInterpolator()
            doOnEnd { splashViewProvider.remove() }
        }
        slideUp.start()
    }

    setContent { AppTheme { MainScreen() } }
}

Always call splashViewProvider.remove() when the animation ends — the system won't dismiss the splash view otherwise.

Keep splash visible during init

For critical initialization that must complete before showing UI:

var isReady = false

override fun onCreate(savedInstanceState: Bundle?) {
    val splashScreen = installSplashScreen()
    splashScreen.setKeepOnScreenCondition { !isReady }
    super.onCreate(savedInstanceState)

    lifecycleScope.launch {
        loadCriticalData()
        isReady = true
    }

    setContent { AppTheme { MainScreen() } }
}

Use this only for data the first screen absolutely requires. For everything else, show the UI immediately and load asynchronously — see startup optimization.

Migrating from legacy splash

Delete:

Replace with:

The system splash shows instantly on tap — faster than any custom splash Activity could render.

Icon sizing

Splash icon guidelines:

Test on circular, squircle, and rounded-square icon masks.

SplashScreen API on Android 12+ vs older devices

core-splashscreen library backports the Android 12 splash to API 23+:

// build.gradle
implementation("androidx.core:core-splashscreen:1.0.1")

// themes.xml — both values and values-v31
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/splash_bg</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash</item>
    <item name="windowSplashScreenAnimationDuration">1000</item>
    <item name="postSplashScreenTheme">@style/Theme.App</item>
</style>

// Android 12+ only (values-v31/themes.xml)
<item name="android:windowSplashScreenBrandingImage">@drawable/branding</item>

On API 31+, system controls splash timing. On API 23–30, library emulates behavior — test both paths.

Conditional splash screen retention

Keep splash visible until critical init completes — but cap retention time:

override fun onCreate(savedInstanceState: Bundle?) {
    val splashScreen = installSplashScreen()
    super.onCreate(savedInstanceState)

    var isReady = false
    splashScreen.setKeepOnScreenCondition { !isReady }

    lifecycleScope.launch {
        try {
            withTimeout(3000) {  // never block splash >3 seconds
                awaitAll(async { initAuth() }, async { loadConfig() })
            }
        } finally {
            isReady = true
        }
    }
}

Without timeout cap, slow network hangs splash indefinitely — users think app is frozen. 2–3 second maximum retention; show loading UI in app for longer operations.

Splash screen theming for dark mode

Provide separate splash themes for light and dark:

<!-- values/themes.xml -->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/splash_bg_light</item>
    ...
</style>

<!-- values-night/themes.xml -->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/splash_bg_dark</item>
    ...
</style>

Splash background must match app's first screen background — jarring color flash on transition signals poor polish.

Failure modes

Production checklist

Resources

Frequently asked questions

Do I need to implement the Splash Screen API on Android 12+?

Android 12+ shows a default system splash screen for every app regardless of your code — your app icon on a themed background. Without the SplashScreen compat library, you can't control its appearance or add an exit animation. Implement it to customize the icon, background, and transition into your app.

How is the new Splash Screen API different from a splash Activity?

The old pattern used a dedicated SplashActivity with a layout that delayed navigation until init completed. The new API is a system-managed splash that shows instantly on tap and dismisses when your first frame draws. No Activity, no layout, no artificial delay — just a themed icon that transitions into your app.

Can I keep showing the splash screen while loading data?

Yes — call splashScreen.setKeepOnScreenCondition { !isReady } to hold the splash visible until your condition returns false. Use this sparingly for critical init that must complete before showing UI. Don't hold the splash for analytics init or non-critical SDK setup.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →