Splash screens in Android 12
Tags: android
Published: 2021-04-13 16:20:48

**2021-05-05:** With dp3 apis and emulator images the splash screens now work as described. I have published a sample app on [GitHub](https://github.com/tkuenneth/android-demos/tree/master/s/SplashScreenDemo).

The Android 12 Developer Preview contains support for splash screens. Even though the api might change until the final release of Android 12, or the feature might even be removed again, it is interesting to see what we know at the moment. 

Curious? Come, join me in my investigations...

First of all, there is a new interface `android.window.SplashScreen`. Currently the docs say:

> The interface that apps use to talk to the splash screen.
>
> Each splash screen instance is bound to a particular
> `Activity`. To obtain a `SplashScreen` for an `Activity`,
> use `Activity.getSplashScreen()` to get the `SplashScreen`.

The interface contains one method: `setOnExitAnimationListener()`

> Specifies whether an `Activity` wants to handle the splash
> screen animation on its own. Normally the splash screen
> will show on screen before the content of the activity has
> been drawn, and disappear when the activity is showing on
> the screen. With this listener set, the activity will
> receive `OnExitAnimationListener#onSplashScreenExit`
> callback if splash screen is showed, then the activity can
> create its own exit animation based on the
> `SplashScreenView`.
>
> Note that this method must be called before splash screen
> leave, so it only takes effect during or before 
> `Activity#onResume`.

Let's try to see this in action. As `SplashScreen` is an interface it is interesting to see the actual implementation.

```kotlin
class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d(TAG, "--> ${splashScreen::class.java.name}")
    splashScreen.setOnExitAnimationListener {
      Log.d(TAG, it::class.java.name)
    }
    setContentView(R.layout.activity_main)
  }
}
```

If we run the code, `D/MainActivity: --> android.window.SplashScreen$SplashScreenImpl` is printed. 

`SplashScreenImpl` is no public api class, still, we can look what it contains during runtime:

![SplashScreenImpl during runtime](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjzax5pywi0fi7zuh783.png)

One of its properties, `mGlobal`, references a `SplashScreenManagerGlobal`. We don't know much about this class, but peeking inside it reveals

![SplashScreenManagerGlobal during runtime](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1tq0s5997p9alpphy3kj.png)

so one of its properties holds an `ArrayList` of `SplashScreenImpl` objects.

While this is interesting, it doesn't help with a major issue of my code: the second output (`Log.d(TAG, it::class.java.name)`) is **not** printed. 

This means that the listener we set using `setOnExitAnimationListener()` is not invoked. Which is a pity, because the docs of `SplashScreen.OnExitAnimationListener` sound great. This interface defines one method, `onSplashScreenExit(SplashScreenView view)`.

> When receiving this callback, the `SplashScreenView` object
> will be drawing on top of the activity. The
> `SplashScreenView` represents the splash screen view
> object, developer can make an exit animation based on this
> view.

So, what do we do?

Maybe it's a timing issue, maybe the app is too fast.

```kotlin
splashScreen.setOnExitAnimationListener {
  Log.d(TAG, it::class.java.name)
}
Handler(mainLooper).postDelayed({
  setContentView(R.layout.activity_main)
}, 5000)
```

No, doesn't help. Let's think again. 

Hasn't splash screen support been built into Android since api level 26 (Oreo)?

Right.

`android.R.attr` contains `windowSplashscreenContent`. The docs say:

> Reference to a drawable to be used as the splash screen
> content of the window. This drawable will be placed on top
> of the `windowBackground` with its bounds inset by the
> system bars. If the drawable should not be inset by the
> system bars, use a fullscreen theme.

In your *themes.xml* file you can add something like

```xml
<item name="android:windowSplashscreenContent">@drawable/anim</item>
```

and will receive a nice splash screen. But my listener still is not invoked (recall that in the last quote the docs refer to **window**). 

What's interesting: `android.R.attr` has been updated for the Developer Preview, too:

`windowSplashScreenAnimatedIcon`

> Replace an icon in the center of the starting window

`windowSplashScreenAnimationDuration`

> The duration, in milliseconds, of the window splash screen
> icon animation duration when playing the splash screen
> starting window. The maximum animation duration should be
> limited below 1000ms.

`windowSplashScreenBackground`

> The background color for the splash screen, if not specify
> then system will calculate from windowBackground.

`windowSplashScreenBrandingImage`

> Place an drawable image in the bottom of the starting
> window, it can be used to represent the branding of the
> application.

To mee it is not clear if these additions cater for the old or new api. So, it'll be more than interesting to see what happens in the next preview and beta versions.

## Summary

So far I have not been able to make use of the new interfaces and classes regarding splash screens. The reason may be

- I am missing something 😂
- I am doing it the wrong way
- Some pieces of the puzzle are still missing

As the docs say the new api is based upon activities, we may need to configure something in the manifest. Still, I have not yet found any evidence backing this assumption.

What are your thoughts about this. Please share your impressions in the comments.