Mar 1, 2017

Getting Started in Android Development: Part 3: Reducing Bloat

So far we have seen Part 1: Building the First App, and Part 2: Publishing the first App.

That Feeling When you build a brilliant piece of software and the users are ripping it from your fingers to the sound of raving reviews:

  • dad: I'm home! Have you seen my first app I've e-mailed you about?
  • kid: Hi. Yup.
  • dad: So?? Do you like it? Have you given it any stars?
  • kid: Just one. It can do almost nothing and it takes up too much space.

And the kid is right. App description: Press a button and get a random number between 1 and 6. App size: 6MB. Six. Megabytes.

In this post we will reduce that over a hundred times to 44KB.

Thanks to SUSE, my employer, for sponsoring a company-wide Hack Week which this project was a part of!

Debug or Release Build?

I did not manage to make a release build in the Android Studio IDE. So I tried from the command line. (J. Reidinger has pointed out that I should read Configure Build Variants.)

$ sudo zypper install java-1_8_0-openjdk-devel       # to provide javac
$ ./gradlew assemble
[downloads some deps at first... 280MB]
[lots of output for normal build too]
$ (cd app/build/outputs/apk; stat -c "%'9s %n" *.apk)
1,443,734 app-debug.apk
1,337,890 app-release-unsigned.apk

Apparently my hopes that a release build would be significantly smaller were unfounded. The APK has 1.5MB and takes up 6MB when installed.

Shrink Your Code and Resources

First I searched the web for "minify android app" and eventually arrived at Shrink Your Code and Resources in the IDE manual.

Using minifyEnabled true in build.gradle shrunk the signed release build from 1,347,038 bytes to 786,674, which results in 2.39MB installed size. (Did not find a way to install this build from the IDE, used adb install -r ./app/app-release.apk.)

Changing proguardFiles from proguard-android.txt to proguard-android-optimize.txt slightly shrinks the APK to 771,406 bytes.

Adding shrinkResources true: 745,490 bytes, 2.21MB installed.

Code Bloat: Activity Base Class

It seems that now the main reason for bloat is the sheer amount of included code: 5 methods of mine vs 4823(!) methods from the android.* classes.

Changed the base class of the main activity from android.support.v7.app.AppCompatActivity to android.app.Activity but then adb install says "Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]". adb uninstall net.vidner.justrollonedie solved it. But I wonder what would happen if my users on the app store wanted to update. Fortunately I have none :D

The base class change improved the sizes to 661,870 APK, 1.62MB installed.

Code Bloat: API Version

I thought a 4x reduction in installed size was good enough, even if still bloated. I decided to fix one more thing before pushing an update to the store: the minimal required Android platform. (In the process of tinkering with a demo OpenGL app I discovered that android-8, supporting my old 2.2 Froyo phone, gets automatically downloaded if I declare it in the app manifest.)

So I did, and the side effect was perfect: all boilerplate code was gone and I ended up with a 17,282 byte APK, 44KB (kilobytes!) installed. Still too much for a microcontroller ;-) but good enough for Android.

Figuring out how to downgrade my code and layout and styles to still run on the older API seemed tricky at first, but then I simply generated a scratch project for android-9 and copied the differences. Then I changed one style name with the help of the API version filter (see screenshot).

Get the App, Get the Source

The source code for Just Roll One Die is on GitHub under a MIT license. You can try out Just Roll One Die on Google Play.

No comments: