How we improved our android app to 99.8% crash free : A quick view

Anuj agarwal
Engineering @ Housing/Proptiger/Makaan
7 min readMay 26, 2023

Here, At REA India, We have always strived for providing a great customer experience while on our mission to help people find their dream homes.

To fulfil that mission, Apps are a big enabler and we are always keen to improve them.

In our Proptiger app, We planned to stabilize and improve our proptiger app and achieved a humbling stable performance.

Here’s a snapshot of the changes we exercised to achieve the same:

Tracking and removing memory leaks

We use memory profiling in android studio and also recently integrated LeakCanary to investigate if any memory leaks are happening in the app and then resolve them.

For those not aware, LeakCanary is a memory leak detection library for Android.

LeakCanary’s knowledge of the internals of the Android Framework gives it a unique ability to narrow down the cause of each leak, helping developers dramatically reduce jank, Application Not Responding freezes and OutOfMemoryError crashes.

LeakCanary taking a memory dump

This exercise helped us immensely keeping our ANRs and Out of memory issues in check.

Dealing with NullPointerException

No matter how easy it looks, Any android developer can tell you how difficult it is to deal with null pointer exceptions in android ecosystem.

Mostly Null pointer exceptions are found in the Android onResume() method. When the application goes in the background, it may have to get rid of some memory, losing many references along the way. To avoid this issue, you can save your data from the onPause() method into a more persistent layer like a local database or cache, then pull it back out within onResume().

There are many null safety functionalities also provided by kotlin. Using them in everyday coding definitely has helped Proptiger App avoid NullPointerException and deliver a stable experience.

Error and Exception Handling

Given the complications in mobile development, some errors here and there are inevitable, whether it’s an API change, a network condition that ends connectivity, a network condition that ends connectivity or a memory problem that avoided the previous detection, or even just slows data speeds during the transmission of large files or even on API calls. What can we do to prevent a crash in such situations is good error and exception handling.

Using proper Error conditions and exception handling, your app won’t run by these exceptions.

In any of these cases, properly coded within your app will handle unexpected situations and have a graceful way to terminate a process or activity while informing the user of the error.

Supporting Multiple Android versions

Android has a vast number of devices running on different versions of android, unlike iOS where most of the users are on the latest iOS.
In Android, mere 13% of users are on the current android version. That itself elevates the complexity an android developer has to take care of.
Not having the functionalities fully supported in all android versions properly. This results in unexpected crashes in older android versions from time to time.

At Proptiger, We support all the way back to API 21, Lollipop.

We take backward compatibility very seriously, Abovementioned issues are addressed by taking the help of version specific Android emulators and using the cloud device service Pcloudy.

Reducing the size of the build

Knowingly or Unknowingly there is always a bunch of code in the codebase which is not used for all, also the resources like some of the images and some parts of the library code can go unused but still go zipped as part of your apk file.

We use Proguard to remove such unwanted code and resources from the apk resulting in a smaller, more compact and having only useful code/

Proguard is free Java class file shrinker, optimizer, obfuscator, and preverifier.

It detects and removes unused classes, fields, methods, and attributes. Enterprises use Proguard in android app development, it optimizes bytecode and removes unused instructions.

We shrinked our app from 26.9 MB to 8.3 MB using this tool.

Build Size comparison, Non-Proguard vs Proguard

Managing multiple live builds

Mobile apps are full peace of software code that resides in the user’s phone. New updates being rolled out don’t mean that it will get updated immediately in the customer’s phone as well. Customers do not update apps immediately. While it’s getting better these days with Android’s automatic updates, it is most likely that you have to keep supporting older versions of the code. Any changes in the Backend API could potentially have an impact on app stability & crashes.

Backward compatibility of the API’s is the key here to avoid getting crashes due to multiple versions of the app. With each new API change, you need to check old versions of the app and make sure your app doesn’t break.

Improving the User experience and Smoothening navigation

We migrated our application from imperative to declarative development by developing it with Android Jetpack Compose, which uses the concept of recomposition.

This also removes boilerplate code, makes debugging and testing easier, and results in a more smother navigation inside the application.

let’s see how Jetpack Compose compiler renders UI elements in the runtime that improves the overall performance.

Jetpack Compose Phases

Jetpack Compose renders a frame following the three distinct phases:

  • Composition: This is the first phase of the rendering. Compose run composable functions and analyze your UI information.
  • Layout: Compose measure and commutates UI information on where to place the UI elements, for each node in the layout tree.
  • Drawing: UI elements will be drawn on a Canvas.

Here are some links that can help you migrate from XML to Android Compose.

https://developer.android.com/jetpack/compose/migration

https://github.com/android/compose-samples/tree/main/Jetcaster

Reducing the download build size

To minimise the app size for users, we shifted from Apk to Android App Bundle, which is a new upload format that includes all your app’s compiled code and resources, but defers APK generation and signing to Google Play.

Google Play’s new app serving model then uses your app bundle to generate and serve optimized APKs for each user’s device configuration, so they download only the code and resources they need to run your app. You no longer have to build, sign, and manage multiple APKs to support different devices, and users get smaller, more optimized downloads.

Our app has ~1MB less size than its peer group

Monitor the crashlytics

You can’t improve crash rate if you aren’t looking at crashes, make sure you’re at least keeping an eye on high velocity crashes.

We have a Crashlytics tab filtered to the latest release pinned on Chrome, and quickly check it each day at least twice to make sure we’re still at our desired crash-free state. Only takes a second, and has caught a few issues before they’ve escalated.

We usually rollout a subversion build with a seemingly fishy issue quickly for the ones we think might escalate in a day or two.

Hitting the goal standard: 99.9%

In the mobile ecosystem especially in Android, It’s recommended that an app should strive to have a crash-free user rate of greater than 99%. It’s the gold standard of any apps in android to have 99% Crash free users, but there are many apps where that will fall below this level at times. Proptiger’s Customer facing Android app has an average crash-free user rate of 99.7% and while a 0.8% gain on the recommendation may seem small, it is very significant.

There are three different ways that we can measure performance of the app: crash-free users, crash-free sessions and ANR-free sessions.

Crash-free users is the percentage of users that have not experienced a crash in the given timeframe.

Crash-free sessions is the percentage of total sessions that have not resulted in a crash in the given timeframe.

And ANR-free sessions is the percentage of total sessions that have not resulted in a ANR which is essentially freezing of the app in the given timeframe.

All three are equally important to track -

Crash-free users give you the visibility of how much percentage of users are affected by the crash.

Crash-free sessions point you to how frequently the app is crashing.

ANR-free sessions point you to how frequently the app is freezing.

At Proptiger, We are proud to share that we’ve achieved the following numbers:

  • 99.8% Crash free users (for most recent build, 99.7% overall)

99.8% crash free users on our most recent build

  • 99.9% Crash free Session
  • 99.9% ANR(Application Not Responding) free Session

One of the main reasons we’re so proud of our numbers is because of the work we’ve done to get it there. When the app was first launched, we had about 5–6% of users getting crashed.

Closing Remarks :

Although 99% crash-free users are good enough numbers, every developer should truly try to reach as close to 99.9% crash-free users for their app.

At Proptiger as well we did many efforts to reach 99.5+%. All the learnings shared above have helped achieve this number.

I hope you found the article interesting & useful. If so, feel free to like and comment and share your views.

--

--