Time’s a funny concept. In my everyday life, I hardly ever notice when individual seconds go by. I have to be really anxious that I’m late, drawing a blank during a test or sitting in a dentist’s waiting room in order to feel the seconds slipping through my fingers.
Or I could be using a smartphone. If there’s one thing that can cause the ordinary calm person to lose his temper, is waiting for his phone to respond. Yes, me too… The longest moments of my day are spent waiting for an app to launch once I clicked on its icon. If I need to check when the next bus is or order a taxi, for instance, my foot begins to stomp and my fingers start fidgeting.
In Android, for instance, the launch timeframe is the interval between the application class’s onCreate and the launcher activity’s onStart. Only once onStart has been completed, will the lucky user view the opening screen. This timeframe can span from a mere couple of milliseconds to several, noticeable seconds.
The OnCreate Complexity
You see, most SDKs aim to be placed in the application’s onCreate. It gives them the chance to get into gear at the earliest possible time, thus guaranteeing a much more holistic and tight solution. Makes sense. After all, what good is a crash reporting library that fails to catch a crash? Or an analytics library that leaves a part of the app unturned?
However, there’s a price to be paid. This section of the lifecycle occurs even before the user receives any indication that the app is actually responding. The user is just staring at a blank screen, waiting. You know the feeling.
The more SDKs you have implemented in your app, the more they block the main UI thread and the longer you’ll keep your users waiting. Bugger.
Waiting For the Other Shoe to Drop
To be fair, most SDKs do very minimal work during their initialization. Usually, the longest potential task is that of pre-loading data from a server (such as ads, settings etc.) Thankfully, Android doesn’t allow network communication on the main UI thread, so this task should be thrifty in nature. But alas, “coulda, woulda, shoulda“, and we need a reality check. Some SDKs make sure their data has been received by stalling and waiting for a callback before “releasing” the main thread back to the application itself… And Huston, we have a problem.
When the amount of work done by an SDK depends on network connection, the best thing to do is not to place it in the onCreate. Even if the SDK’s documentation says it must be placed there, simply be the king of your own app and decide what’s best for you. After all, splash screens were created for a reason.
The Good, the Bad and the Unzipped
Surprisingly enough, waiting for a network request to finish is not the longest task we have found to occur during an app’s start time. Some SDKs actually use this time to load additional code.
Some context is required. While today the issue of breaking the 65K limit is practically a non-issue, times were when SDKs and app developers attempted to avoid it at all costs. SDKs did not wish to be the proverbial last straw. Before the multidex solution was official, SDKs took some extreme measures to mimic this solution themselves. This means SDKs would load additional code during runtime, much like the secondary dex files are loaded today.
But you know what they say: “If it ain’t broke, don’t fix it”. And so many SDKs never changed the way they work. To some degree it even allows them an additional amount of obfuscation, so why change it?
Well, here’s one reason why. Take a look at the following analysis we did for an app at SafeDK. The following graph displays the distribution of the app start time by SDK:
As you can see, the app is only responsible for a third of its start time. The rest is spent on SDKs. Two of these SDKs also take nearly a third of the start time each. The app takes nearly 3 seconds before it responds and nearly 2 seconds of that is because of these 2 SDKs.
And why? Because the app’s APK is distributed with zipped dex files that the SDKs then unzip and load dynamically when the app is launched. That’s right – it’s not just a secondary dex file being installed with a dynamic ClassLoader (using the SDK’s code, not Android’s), it’s also a much prolonged process of unzipping a dex file.
Check Yourself Before You Wreck Yourself
The following chart displays the same app’s start time distribution, this time after several usages:
Things have changed: The app start time has dropped a bit, the application is now responsible for nearly half of its start time (not just a third), and only one SDK is responsible for the remainder.
So why did one SDK start time shrink while another didn’t? Well, the orange SDK first checks if it has already unzipped the file by checking if the destination directory holds the file. If so, it only loads the dex file. However, the blue SDK never checks and every single time the app is loaded, unzips the file as well. Even if it has already unzipped. Even if the app was last launched within the same hour. Even if it was last launched just a minute ago.
Over time and on several devices, the orange SDK affects the user experience only during the first launch. It’s not ideal, sure, but at least it’s just the first time. The blue SDK, however, always slows the app, every single time. It constantly prolongs the time it takes the app to respond.
You can see it much more clearly in our “Duration Over Time” graph, where both SDKs can be seen to take hundreds of miliseconds during the first app launch, however while one SDK drops to an insignificant amount of time, the other SDK still takes up hundreds of miliseconds each time the app launches:
The best course of action for the app developer is, of course, to move this entire SDK’s initialization code to a splash screen or alike, or even replace that SDK with a similar one that offers the same functionality but with less consequences to the user experience (and, coincidence of all coincidences, SafeDK’s Marketplace is just the place to look for the optimal SDK for you, as well as rate and review the SDKs you’ve had the pleasure or displeasure of employing in your app).
The time that passes from the icon click to app launch is critical. First impression matters (some say matters most) and app developers should strive to make waiting time as short as possible. Use a splash screen if you have to. It’s not ideal, but it’s better than nothing.
If your SDKs are significantly prolonging your start time, move them to the splash screen or replace them with other SDKs. you can explore them in the SafeDK Marketplace.
Not sure why it takes your app so long to launch? Suspect it might be one of the 3rd party tools you are using but not sure which? Sign up for SafeDK’s In-App Protection and get SDK-oriented live data and real time alerts for any increase on SDK start time or other issues.