Why to do it?
According to Google's internal data presented at I/O 2017, there are 2 significant issues you can face if your .apk size is too big:
- Users tend to cancel downloads of large applications (Cancellation rate for apps that get close to 100MB is almost 20%!)
- When users will eventually fill up their phones with photos, videos, and other applications, they will run low on memory. They will try to find some spare space by deleting applications. Research shows that apps that exceed 100MB are even 8 times more likely to get uninstalled.
We don’t want our users to resign mid-download. We don't want them to remove our application either. So what do we do? We reduce size. How do we do it? There are several ways to slim down our file-size. I would like to go over a couple of them in that post.
Smart choice of drawables:
We want our applications to be pretty colorful - rich in graphics, icons and pictures. We want them to be eye-pleasing. Therefore we pack them with tons and tons of custom resources, shiny icons, polished pictures, great banners. That’s totally fine and I for sure encourage you to do that. Remember however to do it smart. There is one rule to always follow - if you can use .svg instead of multiple PNGS for every screen density, do that.
Fairly low complexity vector drawable is often smaller in size than its hdpi qualified equivalent. Note that we also need mdpi, xhdpi and xxhdpi qualified images to support different screen densities. That provides a huge save on memory and it is super easy to do. Additionally, for simple icons, you can use the built-in tool for creating vector asset (New -> Vector Asset).
You can also convert existing PNG drawables to WEBP drawables using an android studio. This method also saves tons of size in the long run and is also able to handle more complex images but it has some drawbacks. More about conversion to WEBP can be found here:
Do not use enums
While enums are great for clean - code style, they bloat our application through the roof. Single enum declaration can (according to Google documentation) add up from 1.0 to 1.4 KB to the size of your application dex file. That accumulates quickly to large numbers in bigger applications. Replace your enums with IntDefs, to keep it small, and in case of most use-cases, essentially the same. To learn more about IntDef please follow the link below:
Reduce your amount of code.
Before publishing, make sure to go over your application and check what is really needed, and what is not. For example, sometimes you just do not need all the getters and setters for your model class. Make sure to reduce that generated boilerplate wherever you can. Those are small changes, but they add up to big saves in case of memory footprint, especially when your project starts to grow.
Moreover, remember that every additional external library brings tons of internal dependencies to the game, bloating up your project size and increasing memory count. Reconsider usage of external libraries and keep only those essential to your app well-being.
Use Proguard to minify code and shrink resources.
Adding just 2 lines in your Gradle configuration can save tons of space. There are 2 things you want to do:
- Enable code minification
- Shrinking of resources
Minify option renames all your classes and methods to simple names like “a” or “b” to save some extra space. It also searches for “dead code”, which is code not connected to any entry-point of your application, meaning it will never be called. That results in lower classes.dex file size as well as reduced method count. The second option does more or less the same for resources. The configuration is really minimal:
For the purpose of this article, I created a simple application, with just 1 activity, displaying list of some elements. Even though the .apk size was very small, i was able to slim it down even more using ProGuard.
ProGuard handles android libraries well, but when it comes to external dependencies, like Retrofit or Picasso you may have to add custom rules to you proguard-rules.pro file, located in the root directory of your project. To help you out I found a list of rules for some of the most popular libraries used widely in Android development. :
Coming up: Downloadable fonts.
Android Studio 3.0 supports downloadable fonts now. It means that we do not have to put the actual font file inside our app, but rather declare what fonts we will be using, and the google’s Font Provider will fetch that font for our application. It will reduce the size of .apk files on our side as well as reduce the download size for the user, since one font can be provided to multiple applications on users phone. To use them, simply specify the font you want to use on a TextView in the design tab of your layouts xml file. You can open a picker window by selecting "more fonts" option. You can also choose if you would like the font to be bundled with the apk file or rather create downloadable font.
Coming up: Aapt2.
Aapt 2 is a tool that crunches app resources as well as prevents resource duplication. I was able to save additional KB’s in my simple sample project just by adding one line to gradle.properties file. However, this tool is available in Android Studio 3.0, so if you have a lower version of Android Studio you might have problems running it :
Your .apk file size is something you should care about since day 1 of your project's development process. Maintaining low memory footprint leads to less canceled installs and more instances of your application preserved on users devices. The ways I presented are only some of the things you can do. For more information head to https://developer.android.com/topic/performance/reduce-apk-size.html
Keep it small! ;)