Shared publicly  - 
 
Use cold start time effectively with a branded launch theme
Pro-tip by +Ian Lake

When your app isn’t in memory and is launched, that ‘cold start’ can take significantly longer than if your app is already in memory. Depending on the size of your app and what you’re doing in your Application’s onCreate() (as little as possible I hope!), there may be lag between when the user starts your app and your Activity’s onCreate() is actually called. During that time, the window manager makes its best effort to draw a placeholder UI using elements from your theme such as the background and status bar color.

But the background doesn’t have to be a solid color: it can be an opportunity to add a little more personality and branding to your app without slowing down the user through the use of a branded launch screen (http://goo.gl/gp6FDE), allowing your app UI to focus on content rather than additional branding. The key is creating a custom theme that overrides android:windowBackground, then replacing that custom theme with your standard theme before calling super.onCreate().

Assuming you have a theme called AppTheme, your launcher theme would be:
<style name="AppTheme.Launcher">
  <item name="android:windowBackground">@drawable/launch_screen</item>
</style>

This implies that everything about the launcher theme is inherited from your main theme - you’re just changing the windowBackground. One other attribute you may consider changing here is colorPrimaryDark: the status bar color on Android 5.0+ devices. Setting colorPrimaryDark to your main background color can put more emphasis on your branding at the expense of another element changing when transitioning to your final theme.

But drawable/launch_screen can’t be just a simple image, unfortunately - it’ll end up stretched to fill the entire screen. Instead, you can use an XML file such as:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
  <!-- The background color, preferably the same as your normal theme -->
  <item android:drawable="@android:color/white"/>
  <!-- Your product logo - 144dp color version of your app icon -->
  <item>
    <bitmap
      android:src="@drawable/product_logo_144dp"
      android:gravity="center"/>
  </item>
</layer-list>

Make particular note of the android:opacity=”opaque” line - this is critical in preventing a flash of black as your theme transitions.

Then apply your theme to your activity in your AndroidManifest.xml using android:theme="@style/AppTheme.Launcher".

The easiest way to transition back to your normal theme is to call setTheme(R.style.AppTheme) before super.onCreate() and setContentView():
public class MyMainActivity extends AppCompatActivity {
 @Override
  protected void onCreate(Bundle savedInstanceState) {
    // Make sure this is before calling super.onCreate
    setTheme(R.style.Theme_MyApp);
    super.onCreate(savedInstanceState);
    // ...
  }
}


Things to note with this approach:
- No launchpad activity - there’s no delay such as there would be if you were launching a second activity from a dedicated splash screen style activity
- No artificial delays - you’re only using the time that you have, just taking advantage of theming
- No extra overdraw - resetting your theme removes a layer of overdraw compared to having an opaque view with your normal background above the custom windowBackground
- Only for your launcher activity - this isn’t appropriate for deep links into your app or handling a URI, but for launches done through the home screen - the point is to minimize dead time, not to annoy users.
- Fast is best - keeping your app lean and minimizing work done at startup is critical to a good experience, even if that means slightly less time for branding - remember: getting users to the content they care about should be your #1 priority.
- Watch your transition - keep both the number and complexity of your transitions to a minimum by sharing as many elements (colors, etc) as possible to make for a seamless transition straight to content.

#BuildBetterApps  
472
246
Jahir Fiquitiva's profile photoBoopathy Raja's profile photoEduardo Pratti's profile photoIan Lake's profile photo
94 comments
Ian Lake
+
2
4
5
4
 
Note: if you want to specifically match what you see in Google apps, add android:bottom=”@dimen/product_logo_bottom” to the product_logo_144dp item where product_logo_bottom is 16dp, 48dp (land), 24dp (sw600dp & sw600dp-land), 64dp (port-v21) and 72dp (sw600dp-port-v21 & sw600dp-land-v21).

The brand name at the bottom (the ‘Google’ in Google apps’ launch screens) would be a 48dp high grayscale image with gravity center_horizontal|bottom and an android:bottom of 48dp, 56dp (sw600dp), 104dp (port-v21), and 96dp (sw600dp-port-v21 & sw600dp-land-v21). A visible brand name is certainly not required, but can provide consistency if your company has multiple apps.

We’re still tweaking numbers and would still suggest centering your image as in the post itself, particularly in cases where you are not using a brand name.
 
Yeah, about that cold start time... Has it increased for all apps since ART was introduced? Because I seem to recall it wasn't so high back in pre 5.0 era. Or am I just imagining stuff? If so, it's kinda awkward to introduce a splash screen alternative just to suppress the side effect of a new compiler...
 
This is more than a protip. This way more important. Play Store is full of wrong/awful implementations of splash screens. This should go into - > d.android.com
 
It would be awesome to have this on Shuttle, sir +Tim Malseed​! The app usually takes about 1-3 seconds loading while I see a black screen on my Moto G.
 
+Bogdan Zurac​ I don't think start time has actually increased but the perceived start time has, because of the Toolbar and the new AppCompat implementation the launch screen can't show the dummy ActionBar anymore.
 
I don't understand the point about "only for launcher activity". Surely the nature of Android is that you can "cold start" on any screen if you were destroyed in the background. Will this be noticeable if used on a screen which is normally deep-linked?
Waza_Be
+
2
3
2
 
+Christophe Beyls Wouldn't it be a better solution to work on fixing this and displaying a dummy Toolbar/Actionbar rather than displaying a useless fullscreen logo?
 
+Waza_Be - you can do both. The same theme swapping works for action bar themes to NoActionBar themes (with some extra work).
 
+Bogdan Zurac - nothing in ART/framework has made apps slower to launch, but average app size increasing is perhaps a different story and that certainly has an effect on startup time.
 
+Waza_Be​​ This can't be fixed automatically because:
- Toolbars may have various heights
- They are mostly used inside layouts so the theme can not include them.
The only solution to get the same behaviour as before would be to create a custom splash theme with a background which looks like a Toolbar, then swap the theme (just like described here). Since the splash theme is created directly from the theme xml defined in the manifest before any app code is executed, this splash background can not be created programmatically.
Waza_Be
+
2
3
2
 
+Christophe Beyls​​​
-> Toolbar height can be fixed with an animation from standard height to final height that would start when the application really reaches onCreate.

 
Good stuff. Posted a much less in-depth version of this tip a few weeks ago when I went digging in Google Maps' code. 
I agree with +Said Tahsin Dane​. This should be in the docs or the Dev blog.
 
Learn something new , thx for this tip!
 
+Ian Lake how to add the brand logo? in the drawable launch_screen.xml? when yes it doesnt show by me :/ 

<item>
        <bitmap
            android:src="@drawable/tc_brand"
            android:gravity="center_horizontal|bottom"
            android:bottom="@dimen/product_logo_bottom"/>
</item>
 
Is there a way to make this screen to stay at least X seconds? In my app it is too fast.
 
Now I have the anti-problem that the splash screen flashes by too quickly. Should I put a thread sleep in application onCreate (will that even work?) Or should I just go back to doing splash screen activities, again.
 
cannot run emulator AVD error too slow
 
+Yoav Sternberg +Greg Ennis   You can do it by calculating elapsed time at Application's onCreate. Then calculating remaining time and calling Thread.sleep() with remaining time.

@Override
    public void onCreate() {
        long total = 4000; // 4 sec.
        long timestampStart = System.currentTimeMillis();
        super.onCreate();

        // TODO: Do extra stuff here

        long elapsed = System.currentTimeMillis() - timestampStart;
        long remaining = total - elapsed;

        try {
            Thread.sleep(remaining, 0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

Still I am not sure displaying the brand for a long time will give you any advantage. Like the article mentioned the goal should be skipping coldstart as fast as possible and displaying the content.
 
+Yoav Sternberg+Gökhan Barış Aker​ don't do that, see fast is best at the bottom of +Ian Lake​’s post. You don't want to make users wait just because you want to show your brand. It's annoying especially if the app is already cached by the system
 
+Yoav Sternberg the snippet is for application's onCreate callback. It tries to ensure the window background to be visible at least 4 seconds. You can adjust it to 1 seconds by changing total variable value to 1000. I hope this helps
 
Thanks +Gökhan Barış Aker that is what I need. I understand engineers dont want to delay app start however thats what the clients want. Everyone wants everyone else's app to start as fast as possible. But their own app, they want to see their own beautiful logo and have time to admire it before the app starts :)
 
+Ian Lake Multidex. Does Android show this "splah-screen" even before it loads apk classes? This kinda makes sense, 'cause one of the main drawbacks of multidex loading on API<21 is slower startup..
 
+Ian Lake  if using a  animation-list  to the theme. but animation-list  not start play automatically.  how to using a animation as the launch background?  Can we?
 
+ryan cheng - unfortunately no, animations are not supported.

Remember the system is spending as much processing power as possible getting your app started - I have a suspicion that running a nice smooth animation would slow down things considerably (particularly on the slower devices that already have the longest load time).
 
+ryan cheng I would go with a still image that resembles the first frame of animation and then start a launcher/splash activity that will play an animation or video after the coldstart.
 
+Ian Lake Why Isn't the "104dp (port-v21)" value for the brand name the same as the default 48dp value? Is there any difference with the navigationbar on pre v21 devices? 
 
+Mete Polat - The -v21 versions are different as AppCompat on v21+ (and the Material theme if you use android:windowDrawsSystemBarBackgrounds="true") paint behind the system bars, requiring you to take into account the area under the navigation bar when building your windowBackground.
 
I can't understand why Google is advocating splashscreens. Your own apps like maps, you tube looks bad with launch screens, Why are you putting all worst ios ideas in Android?
 
+krupal shah - just a reminder that this cold start window background has always existed - something is always shown while your application starts. This just takes what is sometimes a blank white screen and makes it a bit less empty. It isn't advocating as much as 'if you're going to do it, do it right.' and obviously these branded launch screens were a thing well before this post.
 
+Ian Lake Thanks for the comment. But there are many scenarios when users hate launch screens...especially like this one: https://plus.google.com/u/0/+JuhaniLehtim%C3%A4ki/posts/D3xiDosRGpA . I reviewed some users and frankly, all of them didn't like launch screens showing in apps like Google Maps. Even if there is a blank window background, user can afford to wait because they will be assured that their location will be shown immediately after that cold start. They CAN afford to wait because they will be eager to see their location or data as soon as application starts; not the logo or brand. No offence but you guys should think twice, also get reviews from developer community. Although, there are more apps having launch screens on playstore, the ratio of developers who hate new launch screens is far more than who like to put. Even UX designers do not agree that it is a good idea to put launch screens on start of applications. I remember the I/O 2013, when everyone liked to teach not to put splash screens in app. Even the questions for splash screens were highly downvoted on SO. We devs tend to obey the rules and so we have to put. Otherwise, launch screen is really a bad idea. 
 
+Ian Lake When we taking into account the area under the navigation bar when building the windowBackground using AppCompat on v21+, what about devices with no soft navigation bar?
 
+Vasili Chyrvon - unfortunately, there's no resource qualifier that would allow you to change the dimension based on the existence of software navigation keys. As it is now, they just sit higher on devices with hardware navigation keys using the Google provided values.

Do note the first comment on the post where we recommend centering the image - particularly if you're not using a brand name, this will give a consistent experience on all devices.
 
Say no to splash screens!
 
+Walmyr Carvalho - I'd really encourage you to not use a login activity as your launch activity. Instead, build for the common case (the user is logged in) and handle the uncommon case as a redirect to a login activity before your setContentView() in your main screen (and/or every logged in screen)
 
Wow, just think about it a few days ago.
Im new to Android and Want to ask additional quick question about the best practices.
Often meet in tutorials the way of dealing with different resources via use of member variables and if condition, for xmpl.: if(mTwoPane) { use fragment } else { call another activity }. It makes the code sometimes difficult to read. Is there a way to write it shorter using inharitance? Something like this way:
class MainActivity with child TwoPainActivity.
In the MaintActivity: if mTwoPane  Start activity TwoPaneActivity. And vise versa.

Or coding in such a way will influence app performance?Г
 
But it is weird, that startup time of Google Maps or Google+ apps are now subjectively slower than before and it looks like everyone hated splash screen :-(
 
+Tomáš Procházka - interestingly, user studies across a wide variety of users showed that the majority thought the apps were opening faster with a branded launch screen (compared to the previous empty screen). YMMV I guess
 
+krupal shah Hi, we use this because when the app first launch, it take some time to load up memory, u will show a full white screen, and it definitely showing nothing and full white screen, it just make us use the free white space showing a logo instead, and sorry, my english was poor.
 
Masking androids lag, this is quite pathetic, the focus should be eliminating this lag
 
+Ian Lake I just tried this and its great , but there is one little problem. 

When app has more activities and user press home button on other activity(for example chat in hangouts) and then if app is killed by the system because of low memory, when user opens the app again it opens  chat activity(hangouts example) and when back button is pressed splash screen is showed and than main activity(list of chats in Hangouts, list of radios in my app). 

Is there any way to change this, because I have foreground service that plays music, and when user opens the app from notification and tries to go back the splash screen is showed(if app is killed because of low memory). 

Is there a way to show the splash screen only when main activity is started from the launcher icon ? 

Thank you.
 
+Brane Petkoski​ you are just displaying the theme while the app is starting, so.... yeah. If your app is not running (has been killed by the system) then the Launcher theme is going to display while it starts back up and the ui is being built.
 
+Marty Ballard I know, I am not saying this is bug or something, I know that's normal behavior. 

But I want to know is there a way to determine if app is launched from launcher and only then showing the theme. 

Because showing splash screen on back button is not good imo. 

Imagine you are listening radio and browsing , in the main time app is closed because of low ram, suddenly you want  to change station and you tap on notification and tab back to go to list of station. In this scenario showing placeholder ui is far better than splash screen.

 This might be annoying if user have device with 1gb of ram.
 
I've read an article about this, called "Splashscreens - the right way", long before this post. Anyone relate?
 
+Kata Lune​​ You're right, it's bad practice. I was just saying, there are things in common
 
+Ian Lake Does this method still work on API 21+? I see it on the older phones, but the newer phones or emulators just immediately animate my activity's content. Is this because of the faster load times on those devices?
 
+Austyn Mahoney - Yes, this approach works on all API levels. You can add a Thread.sleep(3000) before your setContentView() if you want to see what it would look like on a slow device.
 
+Ian Lake Even with Thread.sleep(3000) on a Nexus 6P, the image never shows up for me. The launcher actually waits to start the default activity launch animation until after the Thread.sleep(). It doesn't seem to ever show the launch theme.

I am not customizing the start/end animation for this Activity either.
 
Does Google has own Placeholder UI example for cold start?
 
+Ian Lake The centering of the background image takes into account the status/navigation bars on v21+. When the Activity has loaded, I'm wanting to overlay this with the same image and then animate it to a different location. However, centering the ImageView results in the two images being misaligned (unless I set windowDrawsSystemBarBackgrounds to "false") - any suggestions?
 
+Ian Lake​ on the android:src="@drawable/product_logo_144dp", the app icon which is 144x144px right? But the app icon on my splashscreen shows a bit blurred, not sure if I did something wrong :/

Edit:
It's fine now lol, I have to place the image on its respective drawable density folder.
 
+Ian Lake is it somehow possible to show progress bar in @drawable/launch_screen or on top of it? It can be seen in Google Play Music app when it's launched for the first time.
 
+Yuriy Yunikov - nope, nothing animated in your windowBackground. This falls under the 'seamless transition' part - if the layout you inflate in onCreate() has the same background as your windowBackground, then you can add your progress bar to that layout and have it appear as if it was all part of the same loading process.
 
+Ian Lake +Chris Banes 
I've tried to do this but using Vector Drawable Compat.
Instead of a <bitmap> I've put:

<item
android:drawable="@drawable/vector_logo"
android:gravity="center"/>

Of course I turned on AppCompatDelegate's support for VD etc. It looks nice on L and above but for <L where support vectors are used my icon is stretched to fill entire screen. Can I do anything about it? I would like to stick with vector asset.
 
+Ian Lake What if the launcher activity has multiple entry points like notification's pending intent? I just tried and the launch screen is shown only when the entry is from launcher app and not from the notification's pending intent. Is this just a coincidence?
 
+Vairavan Srinivasan - just a coincidence.

There's always a really good chance that the app is already in memory right after it creates a notification (since, by definition, it was active to post the notification).
 
+Ian Lake Thats what i thought. So i tired finishing the launcher activity (without any notification) and made sure the process was alive (it is empty process by now) and then tried launching from launcher app and i do see the brand logo.

Anyways, what is the recommendation for such cases?
 
+Vairavan Srinivasan - this seems to be the third time in the comments on the post we've covered this scenario, so I'd suggest reading comments farther up. I don't know if there's a good use case for being more fancy here - you'd just be replacing your brand logo with a giant white screen in those cases, which doesn't seem very useful.
 
+Ian Lake Sorry just read the first few comments. In my case, I'm trying to avoid the logo screen for notification clicks, it might seem like the app is restarting but I see your point of a blank white screen. It's even more confusing that I can't reproduce either behavior in my test app, nexus 6p. Will run more tests on a older device.
 
+Ian Lake Yeah, it was just a timing issue. On a older device, i could see the brand logo when launched via PendingIntents too.
 
I can't see to get my image to fit the screen, it stretches on some devices to be bigger than the screen. I have the different sizes ones in the proper l-xxxhdpi folders
 
+Tanner Summers - yes, fitting is specifically not what this does and why the single centered icon is the correct pattern to use.
 
I have a webview app I want my splash screen to load till my webview loads my splash screen is visible for sometime then white screen comes after that my webview loads...
 
ohh that image must be in proper size. I tried 2078x3521 PNG (32 bit color) 2.9 mb in emulator n screen jst displayed blank white. bt smaller image worked well.

 
How do i add a Text to style as per above method.

Obviously for gradient background of splash screen, i am using separate drawable xml.

i have to use TEXT heading followed by screen centered Logo
 
+Ian Lake

You said the brand name would be a 48dp image...
Can you please tell me the best dimensions to make it, in terms of pixels?
Thanks in advance.
 
Hi

In one of my app, I am initializing some contents in

public class AppApplication extends Application {
........Contents are initializing when App loads........
}

It took nearly 8 Sec. So to avoid Black Screen i am using

<item name="android:windowBackground">@drawable/background_splash</item>

Issue is that background looks like freezed while loading content for 8 Sec..

Is there is any way to animate the bitmap in "@drawable/background_splash"?

// background_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:gravity="center">
<color android:color="@color/colorPrimaryDark" />
</item>
<item
android:bottom="48dp"
android:gravity="center">
<bitmap
android:gravity="center"
android:src="@mipmap/ic_launcher" />
</item>

<item
android:bottom="100dp"
android:gravity="bottom|center">
<bitmap
android:gravity="center"
android:src="@mipmap/ic_launcher"
android:tint="@color/white_20" />
</item>
</layer-list>



Or is there is any other approach to solve this issue
 
+Ian Lake​ You previously said in this thread that animated splash screens were impossible. Snapseed 2.0, somehow, implemented them.

Did they figure out a way to make them animated or did they reduce the cold start to something extremely close to 0 milliseconds? 
 
+Eduardo Pratti - yep, still no animated launch themes, just good optimization and a really good transition effect from the launch theme to the activity. Much of Snapseed's processing is native code, which can be lazy loaded.
Add a comment...