Shrinking Your Build With No Rules

and do it with Class(yShark)

Lately, we have been working with an important framework that provides a crucial functionality to our product.

As you can imagine, this SDK is pretty huge and it comes with some handy 45k methods: more than enough to make our product (that already makes use of Support Library and Play Services) feel the urge to use the mighty MultiDex.

Diving into the libraries

Getting rid of the unneeded parts of the latter libraries was fairly straight forward, but understanding how to trim the aforementioned framework was another story: the product needed to be included as submodule of our project, thus allowing the 4 files .so and the 3 .jars to be linked properly. The native libraries, built upon a specific platform, come with a .so extension and are usually placed into the folder related to the system architecture, such as x86 or armeabi.

The only choice, at this point, was to just leave this whole monster out of ProGuard’s reach, but that would have affected, if not the need for the MultiDex itself, at least the final size of the APK, bringing it to almost 50 MB. That is, for sure, not ideal: whenever we publish an update, all the users have to download the full sized APK, that will be decompressed and take even more space on each device. Space we don’t really need to take.

The old way of trimming

A few weeks ago, we would have gone with the good old ApkTool, decompiling each of the libraries, finding manually all the references, browsing the single files with Atom or Sublime Text and possibly wasting a huge amount of time: while ApkTool is great when it comes to decompile APKs, for this specific task we needed something different, more flexible and, possibly, more helpful.

Meeting the Shark

Luckily, there is such a tool: ClassyShark.

We can see a native library being decompiled with ClassyShark

This software was exactly what we needed: by simply opening the root .jar from the menu, we could easily follow the different dependencies of each of the methods that we were calling, almost as we were browsing the source code in the IDE.

For instance, by double-clicking on a type declared in the decompiled library, you can easily open up that class and follow the list of dependencies.

Moreover, if somehow you cannot find the wanted file, you can always search for the class with the case-sensitive input field at the top of the window.

With the help of ClassyShark, we could “easily” retrieve all the dependencies that we needed to save and add the proper rule for ProGuard in a very short time, saving ourselves from the headache of manually following the chains or even just trying and compiling to see what references were eventually missing.

The end of the day

Unfortunately, we could not get rid of the MultiDex library but we did shrink our build and the release version of our APK is now about 13 MB, losing about 75% of its initial size. If not a complete victory, it is pretty close to being one.

Thanks to my colleague Giuseppe and to my friends Boris, Mario and Sebastiano for proofreading this article.