Splash Screens on Android
The sample code from this article can be forked on GitHub
Table of Contents
At some point you may find yourself needing to implement a splash screen for your Android app. Reasons for doing so include matching an existing design for iOS, performing necessary background work at start up, or simply for the visual appeal alone. It should be noted that splash screens are certainly not required in your app. In fact, some feel that they should be avoided entirely. Still, it is not uncommon to come across Android apps that utilize a splash screen.
This article provides a detailed outline for implementing a splash screen on Android. While the implementation is relatively straight forward, there are a few details that often get overlooked. We’ve also provided a working sample project that can be run on your device or emulator.
First, create an
It’s important that we extend from
Activity and not
ActionBarActivity. This will exclude the
ActionBar from being visible on our splash screen. Next, declare
SplashActivity as the launcher activity in the app’s manifest file.
Our splash screen will now be the initial screen shown when the app launches.
The layout for a splash screen is typically very simple. For our purposes, we will show an
ImageView in the center of the screen.
onCreate(Bundle) we will initialize a
Handler and its corresponding
Runnable that will be responsible for starting the app’s main activity after a specified duration.
Handler is part of the
android.os package and it easily allows developers to utilize a message queue for a thread without having to deal with synchronization and the lower-level threading APIs in Java. In our case, we will use the
Handler to invoke our
Runnable object at a later point in time on the main UI thread without blocking other operations from occurring in the meantime.
The implementation of
run() is straightforward: the app’s main activity (called
MainActivity in the example) is started via an
Intent. The call to
SplashActivity as done and subsequently removes itself from the app’s back stack. This prevents the user from seeing the splash screen again if they back out of the app via the system’s back button.
onResume(), the method
postDelayed(Runnable, long) is invoked on
mHandler and is passed both our
Runnable instance and a timed delay which is measured in milliseconds. This will enqueue
mRunnable onto the thread’s message queue and then dequeue it for execution after our specified delay.
We will also remove
mRunnable from the
onPause() to ensure it doesn’t execute when
SplashActivity is no longer in a resumed state.
Optionally, we can allow the user to dismiss the splash screen prematurely. In
onCreate(Bundle) we can add an
OnClickListener to the root view of our layout.
Now when the user taps anywhere on the screen, the splash screen will be dismissed. If you wish to include this functionality, you should move the body of the
onClick(View) method to a private helper method since it is indentical to the code used in
run() of our
And that encompasses all of the necessary components for properly implementing a basic splash screen. The next section describes how to additionally perform background work when the splash screen is present.
Performing Background Work
A common approach is to perform some background work at start up while the splash screen is active. This can be helpful if there is data shown on the home screen that needs to be retrieved from a network or external memory device. A valid alternative is to display a progress bar or dialog to indicate to the user that a long standing operation is being performed. While a splash screen inhibits the user’s progress through the app, we get the benefit of hiding expensive operations from the user.
For example, let’s assume we wanted to download an image from the network (e.g. a user’s profile image that is shown on the home screen). We can create an
AsyncTask that will do exactly this:
doInBackground(String...) runs on its own thread and performs the actual network call for fetching the image. Both
onCancelled() will run on the thread that the
ImageLoader was invoked from, which is the main thread in our case.
For demonstration purposes we’ve written our own
AsyncTask for retrieving the image. Excellent libraries already exist that perform this operation and more. Note that making a network call requires the
INTERNET permission to be added to the manifest file.
The basis for the implementation of the splash screen will be identical to the splash screen we developed in the previous section. For brevity, we can simply extend
SplashActivity and augment
onCreate(Bundle) to include the execution of our
ImageLoader inside of
onCreate(Bundle) allows the background work to start as soon as the activity is created. Consequently, we can cancel the task in
onDestroy() if it’s still running in order to allow the operation to continue in the background even if the activity is no longer visible.
That is the extent of performing background work while the splash screen is present. The next section explores some of the pitfalls that developers can encounter with a splash screen.
There are a handful of oversights that developers often make when implementing a splash screen. For example, we make sure to remove our
Runnable from the
onPause() and then effectively restart the splash screen duration each time
onResume() is called.
If instead we moved the invocation of
postDelayed(Runnable, long) to
onCreate(Bundle) and didn’t bother removing the
Runnable callback in
Runnable would end up being executed even if the app was in the background. As a result,
MainActivity would suddenly appear on the user’s screen even though the app was no longer in an active state.
It’s also important that we employ a
Handler to delay the execution of our code contained in the
If the main thread is put to sleep in order to simulate the delay, then the user would be blocked from performing any UI actions while the splash screen is visible. This includes the system back button to exit our app.
Likewise, it’s essential that we use an
AsyncTask to perform any background work. Without it, not only do we block the main thread, but we also increase the likelihood of an ANR (Application Not Responding) message being shown to the user. This happens when the system can’t respond to an input event for a minimum of 5 seconds.
Another consideration is how the
AsyncTask interacts with our splash screen. A good approach is to have the splash screen remain visible for a specified duration, like how we did in the first section, and then cancel the background task if it takes too long.
It is not a good idea to have the duration of our splash screen dependent on the background work being completed. Many types of tasks, such as those involving network calls, can take an undetermined amount of time to complete and having a timeout mechanism is important.
Splash screens, while simple on the surface, take special consideration in order to implement properly. Missing even the smallest detail can lead to a poor user experience. Hopefully this article has revealed which areas you need to examine carefully. And while this article does cover the subject at length, it certainly isn’t comprehensive. Several more enhancements could be imagined for a splash screen.