In emerging markets internet speeds are often slow and the price you pay to use it is high. At Jana our goal is help offset that cost and we do it through our app, mCent. There are a lot of problems that we solve everyday to do this, including limiting the size of our APK. It’s impossible for us to provide free internet if users can’t download our app because it’s too big and takes too long to download, or uses all of their data. That’s why when we noticed our APK size creep up to over 9 megabytes we decided to take action. Here’s a few of the things we did to get our APK size back under control.
ProGuard and Resource Shrinking
The first step in shrinking any APK should be getting rid of unused code and resources. Nobody is perfect, unused code gets left around and drawables aren’t removed from the project, both of these cause your APK to grow overtime. Even if you somehow are perfect, chances are you include some libraries, which definitely have code you don’t need. So how do we solve this? Enter ProGuard, a tool for shrinking, optimizing, and obfuscating your code. For this blog post we only care about shrinking, which ProGuard does by searching your codebase for unused references and removing them. By default Android has a pretty good configuration file that you can use, but you’ll probably need to add rules to ignore certain methods that appear to be unused and are removed by mistake. Implicit includes like dependency injection will need special rules, but don’t be afraid! There are a lot of helpful resources out there to get you through this step. Once you have ProGuard up and running you can enable resource shrinking, which will remove all unused resources from your app (including resources in libraries). To enable ProGuard and resource shrinking update your build type as follows:
(If you build with –info turned on you can see a list of resources that get removed, it’s a good idea to clean this up and get them out of the code base. There are lots of free tools to help with this, like ImageSweep for example)
Remove unused resource configurations
While ProGuard and resource shrinking can go a long way, you may still have unused references in your APK. For example, if you use google play services, you are including translations for every language that Android supports in your app. This may sound great, but if you only support a few languages, or just one, you probably don’t need all of them. This is where the ‘resConfigs’ gradle plugin comes in. By adding this to your default configuration you can explicitly state which resource configurations you support and wish to include, it works for languages and screen densities. When size is really an issue, you may want to consider dropping support for Android DPIs that only a small percentage of your users have access to, like xxxhdpi. Sure, the phones that require these resources are top of the line, but for the time being there very few models on the market, it could be worth the slight loss in quality for those users to benefit the majority of your user base.
Using ‘resConfigs’ is easy. All you have to do is specify the configurations you want to keep. Here’s an example where we keep only English and Spanish strings, and support all densities except for xxxhdpi.
Now you’ve got your build tools setup to remove all of your unused stuff for you and you’re probably feeling pretty good. If you use PNGs in your app there is still more that you can do. PNGs are great because of their high quality, but they often have a bunch of extra data that an Android app doesn’t need. Android build tools will do a lossless compression for you by default through Android Asset Packaging Tool (AAPT), however it’s a bit more conservative than other lossless tools like ImageOptim, which will strip out metadata and unused color profiles to cut out a large portion of the images size.
You can crunch images even more with a high quality lossy tool like pngquant, with very little discernable quality degradation. If you decide to crunch PNGs yourself you’ll want to include the following code in your gradle build file to disable the AAPT cruncher:
Before and After
All of this sounds great in theory, right? How well does it actually work in practice? Using each of the these steps we were able to cut about 30% of our APK size, from ~9.1mb down to just 6.3mb! Keeping the size down is the tricky part, stay tuned for a future post where we explore a few ways that will help you monitor and easily crunch newly added resources.
And as always, if hunting down techniques to save users time and money is exciting to you, we’re hiring!