Update 2013-06-25: The technique described in this article is a bit outdated since the introduction of Fragments into Android. To read more about using a Fragment for a splash screen, see How To Handle Common UI Components, a free chapter of my book Android User Interface Design: Turning Ideas and Sketches into Beautifully Designed Apps.

I’ve never been a big fan of splash screens, especially for mobile apps, because people often add them in as a means of throwing branding in your face. It’s like when you play a video game and you have to watch the 10 second video clip by the studio, and then the clip for the game engine, and then the clip for the producer, and then the clip for the lead designer’s dog, and then you finally get to the loading screen that you sit at before eventually being allowed the luxury of accessing the main menu. The point of a splash screen is to show something to the user while loading is in progress. The minimum amount of loading necessary to show a usable UI should be done, and then the splash screen should be gone. Rarely should this ever be more than a few seconds. I recently had to implement a splash screen and, after getting halfway through a solution, I decided to see how other people tackled the problem.

I was appalled to see all the examples of creating an Activity that has an artificial delay before starting the real Activity. Worse, many of them started timers that weren’t canceled when the app lost focus, so they would still start the app if you had backed out of the splash screen and started doing something else. Some even created Threads to put to sleep and then called the stop method on them. The purpose of a splash screen is to give the user an indication that your app is loading–not to create an extra delay before the user can load your app. People don’t like waiting, especially in a mobile environment.

Alright, so what’s the “right” way of doing a splash screen? I recommend waiting until you have a pretty well developed app before even considering the splash screen. For at least half of apps, you won’t even need one. Android apps tend to be light weight and very fast, often presenting a usable interface within a second of tapping on the icon. If you do genuinely need more time, then chances are you are making use of AsyncTasks or Handlers or other methods of putting your long-running code on a separate thread (if you’re not, then you’re doing it wrong). You just need to display the splash screen in your onCreate method and remove it in your AsyncTask’s onPostExecute method, your Handler’s handleMessage method, etc.

I have found that the best method of displaying a splash screen is with a simple Dialog. It’s been in Android since pre-1.0 and is extremely easy to use. You can pass it any layout you want, even with a custom theme. Here’s an example:

/**
 * Simple Dialog used to show the splash screen
 */
protected Dialog mSplashDialog;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MyStateSaver data = (MyStateSaver) getLastNonConfigurationInstance();
    if (data != null) {
        // Show splash screen if still loading
        if (data.showSplashScreen) {
            showSplashScreen();
        }
        setContentView(R.layout.yourmainlayout);        

        // Rebuild your UI with your saved state here
    } else {
        showSplashScreen();
        setContentView(R.layout.yourmainlayout);
        // Do your heavy loading here on a background thread
    }
}

@Override
public Object onRetainNonConfigurationInstance() {
    MyStateSaver data = new MyStateSaver();
    // Save your important data here

    if (mSplashDialog != null) {
        data.showSplashScreen = true;
        removeSplashScreen();
    }
    return data;
}

/**
 * Removes the Dialog that displays the splash screen
 */
protected void removeSplashScreen() {
    if (mSplashDialog != null) {
        mSplashDialog.dismiss();
        mSplashDialog = null;
    }
}

/**
 * Shows the splash screen over the full Activity
 */
protected void showSplashScreen() {
    mSplashDialog = new Dialog(this, R.style.SplashScreen);
    mSplashDialog.setContentView(R.layout.splashscreen);
    mSplashDialog.setCancelable(false);
    mSplashDialog.show();
    
    // Set Runnable to remove splash screen just in case
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
      @Override
      public void run() {
        removeSplashScreen();
      }
    }, 3000);
}

/**
 * Simple class for storing important data across config changes
 */
private class MyStateSaver {
    public boolean showSplashScreen = false;
    // Your other important fields here
}

In the onCreate method, you call getLastNonConfigurationInstance() to get any data that you saved in onRetainNonConfigurationInstance() (if you don’t know what those are, read Faster screen orientation change now!). If you have data and were still loading when the config change was triggered, show the splash screen and continue any loading you need to do. If there is no saved data, show the splash screen and start your long-running processes. In either case, the main layout is set after checking if the splash screen needs to be shown.

The removeSplashScreen method is safe to call at any point because it checks the mSplashDialog for null before dismissing and then removing the reference. Since you will only ever show the splash screen once per Activity lifecycle, there is no reason to keep a reference to it. This is the method you would call in your AsyncTask’s onPostExecute method, your Handler’s handleMessage method, etc.

The showSplashScreen method creates a new Dialog with a custom theme, sets the view to your layout defined in XML (this can look however you want and include progress indicators, but keep the layout relatively simple and verify it with hierarchyviewer), prevents the Dialog from being canceled, and then shows the Dialog. If you need to show the splash screen for more than a couple of seconds, you should catch presses of the back button to finish your Activity. This method also schedules a call to removeSplashScreen() for three seconds later, so the splash screen will go away either when the removeSplashScreen method is called from the long-running task finishing or from the time running out. You can choose to not include this, but you definitely want to handle the back button in that case.

In your res/values/styles.xml file, you might have something like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="SplashScreen">
        <item name="android:padding">0dp</item>
        <item name="android:windowBackground">@android:color/black</item>
        <item name="android:windowFrame">@null</item>
    </style>
</resources>

Obviously, you can customize that to look right for your app, but that gives you an idea for a simple full screen dialog.

That’s all there is to creating a functional splash screen for your Android app. If you’re having problems getting the splash screen to appear, verify that your long-running task is not running on the UI thread (it should not simply be in onCreate but should instead be executed on another thread). If you know any way to improve this or any alternate methods, feel free to add your knowledge in the comments. If you have a question specific to this code, you can ask as well, but questions that veer much from this should be asked somewhere like StackOverflow, where you’ll get a lot more eyes on your question a lot faster. Happy New Year!