A peek inside Jetpack Core Splashscreen
Tags: android, jetpack, android12
Published: 2021-07-17 13:59:51

Android 12 will introduce a new splashscreen api. I have [written about it](https://dev.to/tkuenneth/splash-screens-in-android-12-4jfi) before it was officially announced. Beta 3 includes the final Android 12 APIs and the official SDK, so we devs can start using the new splashscreen api. But what about previous platforms? There is a new Jetpack component called **Core Splashscreen**, which...

> provides backward compatibility for the new Splash Screen APIs.
> This first alpha version contains all the new APIs backported
> down to API 23, with the exception of the icon background.

Sounds cool, right?

Right.

So, let's take a look. At the time of writing the version of the lib is 1.0.0-alpha01, so there may be changes until it becomes stable. On the other hand, the [platform apis](https://developer.android.com/about/versions/12/features/splash-screen) are not complex. Tu use the lib in your apps, please add this dependency to your *build.gradle*:

```groovy
implementation 'androidx.core:core-splashscreen:1.0.0-alpha01'
```

![A look inside the package](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zazzsslr1uwa034bvver.png)

If we peek into package `androidx.core.splashscreen` we see two classes: `SplashScreen` and `SplashScreenViewProvider`. Before we turn to them, please make sure that you have set

```groovy
android {
    compileSdk 31
```

in your *build.gradle*. I didn't and faced an error like this one:

![error: style attribute 'android:attr/windowSplashScreenAnimatedIcon' not found](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7lrsr4gb0gjnk5q2b3p8.png)  

We'll find out in a minute, what is going on there. If we set the correct `compileSdk`, we can build and run our app just fine. To actually see a splashscreen we however need to add a few things. Here's what the docs have to say.

![A piece of the SplashScreen source code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hchc7kfgvewh470zti1a.png)

So,

- the theme of the starting activity must have `R.style.Theme_SplashScreen` as its parent 
- `R.attr.windowSplashScreenAnimatedIcon` must be set
- `R.attr.postSplashScreenTheme` must be set

Your theme file might look like this (if you have one for dark mode be sure to apply all changes there, too):

```xml
<resources xmlns:tools="http://schemas.android.com/tools">
  <!-- Base application theme. -->
  <style name="Theme.JetpackSplashScreenDemo" parent="Theme.SplashScreen">
    <!-- Primary brand color. -->
    <item name="colorPrimary">@color/purple_500</item>
    <item name="colorPrimaryVariant">@color/purple_700</item>
    <item name="colorOnPrimary">@color/white</item>
    <!-- Secondary brand color. -->
    <item name="colorSecondary">@color/teal_200</item>
    <item name="colorSecondaryVariant">@color/teal_700</item>
    <item name="colorOnSecondary">@color/black</item>
    <!-- Status bar color. -->
    <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
    <!-- Customize your theme here. -->

    <item name="postSplashScreenTheme">@style/Theme.MaterialComponents.DayNight.DarkActionBar</item>
    <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>

  </style>
</resources>
```

If we now run the app, we still don't see the splashscreen. Instead, we get a `java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.`. 

So, let's look further.

![Portion of the SplashScreen source code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r43anwymw2sb9kx1tipw.png)

Turns out we just need to call `installSplashScreen()`. Please make sure you do so *early enough* (in any case prior to `setContentView()`).

```kotlin
class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    installSplashScreen()
    setContentView(R.layout.activity_main)
  }
}
```

This way we get a nice splashscreen that is replaced by the app ui once it is ready. But there is more. With the new platform apis you can have cool exit animations. And with Core Splashscreen you can, too.

```kotlin
val splashScreen = installSplashScreen()
splashScreen.setOnExitAnimationListener { view ->
  view.iconView.let { icon ->
    val animator = ValueAnimator
      .ofInt(icon.height, 0)
      .setDuration(2000)
    animator.addUpdateListener {
      val value = it.animatedValue as Int
      icon.layoutParams.width = value
      icon.layoutParams.height = value
      icon.requestLayout()
      if (value == 0) {
        setContentView(R.layout.activity_main)
      }
    }
    val animationSet = AnimatorSet()
    animationSet.interpolator = AccelerateDecelerateInterpolator()
    animationSet.play(animator);
    animationSet.start()
  }
}
```

The animation shrinks the app icon until it is completely gone. I tweeted about this [back in May](https://twitter.com/tkuenneth/status/1389560772418756615?s=20).

You may have spotted something weird. I invoke `setContentView()` when the animation is complete. This may look a little hacky. Especially, as there is `setKeepVisibleCondition()`. The docs say:

> Sets the condition to keep the splash screen visible.
>
> The splash will stay visible until the condition isn't met
> anymore. The condition is evaluated before each request to draw
> the application, so it needs to be fast to avoid blocking the
> UI.

In theory I could return `false` once the animation is finished, but then I need to do a little more concurrency.

Here's how the animation looks like. Please note that the emulator is running Android 11. 😎

{% youtube c9ZEhND4Lqc %}

What do you think about Core Splashscreen? Please share your thoughts in the comments.

---

[Source](https://github.com/tkuenneth/android-demos/tree/master/misc/JetpackSplashScreenDemo)