top | item 15442743

APK Golf: Reducing an Android APK's Size by 99.99%

279 points| jbergstroem | 8 years ago |fractalwrench.co.uk

70 comments

order
[+] kbenson|8 years ago|reply
This is code golf. I mention that because apparently some people are missing the point, which is purely to get the smallest size. This isn't directly applicable to most work you might do, but like many exercises that explore the extremes, useful knowledge can be learned from the attempt.

In a similar vein, there's a classic article on creating a tiny ELF executable.[1]

1: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.htm...

[+] alanbernstein|8 years ago|reply
Jeez, that article ends like The Lord of the Rings movies...
[+] dheera|8 years ago|reply
1.5 MB for an app that does nothing. 1.5 million bytes for nothing. How inefficient we are these days. I really wish it were as simple as this:

    $ cat > myapp.aml
    <!doctype android>
    <head><title>My App</title></head>
    <app activity="MainActivity.java"></app>
    ^D

    $ cat > MainActivity.java

    import android;

    class MainActivity extends Activity {
      void main() {
        android.toast("hello world");
      }
    }
    ^D

    $ android compile myapp.aml

    Could not find a keystore in your home directory. Would you like me to create one for you (y/n): y
    Enter a keystore password: ********
    Confirm password: ********
    Thanks!
    Compiling Java code ... done!
    Zipping it up ... done!
    Signing ... done!
    Byte-aligning ... done!
    Wrote myapp.apk. You're ready to upload to the Play Store!
    $
But no. We must over-complicate things. AppCompatActivity, manifestations of manifests, layers upon layers of gradle BS, keystores, lots of stackoverflow lookups just to deal with byte aligning, signing, etc. And then Android Studio updates itself, breaking your entire project's 79+ files that for a blank app. What has the world come to?
[+] maxsilver|8 years ago|reply
I totally agree with you. But as an Android developer, I know why we won't get to this...

What does this app do on phones? On tablets? On laptops? Where is the header bar (the original has one, yours doesn't). What color is it? What font? What placement? What about users who don't read English? What about users who's languages don't fit in ASCII. What about users who's languages aren't read left-to-right. How should the header bar even be drawn? What about devices that can't draw the header bar as defined? What about devices that were invented before header bars even existed? What about devices whos OEMs fundamentally redefined what 'drawing' even means. MainActivity.java does what? Is it Java 6? 7? 8?. Which of the 26 'Activity' classes are you extending from, and how do you know it exists on the device? How do you know it behaves identically? The .toast method does what? For which phones? On which API release? How long or short should the Toast display for? Your keysigning the app? Which method of keysigning are you using (old or new, they aren't the same). Who's authoritative for the signing (yourself, or Google Play. Those aren't the same either.)

The sample app, with it's 1.5 million wasted bytes that 'do nothing' handles those problems. It's easy to say "I saved 5k bytes by dropping RTL" but... you dropped all RTL language support. People use that stuff. The example steals a pre-made asset from system resources to save space, which is clever until system resources you need aren't there, which happens in the real world. AppCompat is heavy, but it isn't bytes-for-nothing. Some poor souls at Google waste a lot of time making sure developers get a large library of useful layouts and controls that all mostly-just-work mostly-consistently across a huge spectrum of devices and API releases.

No one intentionally sits down and builds over-complicated code by choice (except perhaps Spring). Every layer of the BS here may be annoying and wasteful, but it attempts to solve a real problem a real person had to deal with.

I love the simplicity of your example. But I'm not sure I'd want to deal with the consequences of living in that world.

[+] userbinator|8 years ago|reply
For some amazing contrast, here's a 4 kilobyte(!) binary which renders a 215-second-long realtime 3D scene, complete with music: https://news.ycombinator.com/item?id=11848097

You may rebuke it with "but it's 4KB on top of hundreds of MB or GB of OS and drivers", but so is this 1.5MB do-nothing app.

[+] fractalwrench|8 years ago|reply
Author here - happy to answer any questions anybody might have.

Also sorry for the shameless plug, but the startup I work for is currently hiring: https://www.bugsnag.com/jobs/

[+] citrin_ru|8 years ago|reply
It is possible to get zip archive with slightly better compression rate using 7zip instead zip command:

7za a -tzip -mpass=15 -mfb=257 -ba -bd app.zip app

[+] markcerqueira|8 years ago|reply
Are you guys based out of Bath, UK? Visited it this past summer and loved it! :)
[+] cordite|8 years ago|reply
Where is the screenshot of the app at the end?
[+] HillaryBriss|8 years ago|reply
thank you for an interesting/educational article!

in the section named "Where we’re going, we don’t need IDEs" the sequence of commands creates a file named app.zip at one point:

zip -r app app.zip

but app.zip doesn't seem to be used later. am i missing something or should that be:

zip -r app app-release-unsigned.apk

[+] brink|8 years ago|reply
Kinda cool.. though it also seems pointless or hollow of meaning? "Let's make a package as small as possible while removing everything. Our next feat will be the world's most empty room."

What's more interesting to me is when the app is extremely small, yet still does something useful.

[+] jbergstroem|8 years ago|reply
What made me post the link was that it – disregarding its debatable pointlessness – showed a diverse set of methods and tools that are useful in android packaging.
[+] craftyguy|8 years ago|reply
> Our next feat will be the world's most empty room

Actually, this is incredibly hard to do, since it would require creating a near-perfect vacuum.

[+] mmanfrin|8 years ago|reply
The 'Golf' part in 'APK Golf' or more broadly 'Code Golf' indicates it's an exercise in trying to see how small you can get the code.
[+] saagarjha|8 years ago|reply
I'd like to see how this is done on iOS, since the OS is much pickier about what it will let you install.
[+] warent|8 years ago|reply
So... it's a signed binary manifest file? That's hilarious and fascinating
[+] freecodyx|8 years ago|reply
Do 50 push-ups while gradle syncs. touche
[+] mike_kamau|8 years ago|reply
Beautiful. Someone should do the same for all the Javascript-framework-driven web apps clogging the web.
[+] bdcravens|8 years ago|reply
Given that the app only displays "Hello world" I'm sure an equivalent Javascript library wouldn't be too difficult.
[+] n-gauge|8 years ago|reply
android:allowBackup="true"

But I may want my app to be installed to the sd storage.

On a separate note: can we not recalc the apk v1 signatures via a javascript crypto function?

[+] yjftsjthsd-h|8 years ago|reply
What, is it too big for your internal storage? ;)
[+] ggm|8 years ago|reply
If you depend on shared library or external state, then in the zen sense, it cannot be "whole" in "one"

(sorry)

[+] aw4y|8 years ago|reply
removing support library, layouts...please.
[+] ocdtrekkie|8 years ago|reply
Back when they introduced them, I was pretty strongly opposed, and you can see the effect. We now have half the Android UI shoved in each app package. Back when I started using Android, apps were rarely over 1 MB in size. Now, with no real improvement in functionality, apps are regularly over 50 MB.
[+] Munksgaard|8 years ago|reply
Either I'm whooshing some sarcasm, or you're missing the point.
[+] HillaryBriss|8 years ago|reply
yeah, i had the same thought. this post cannot be taken as practical advice. interesting to see just how much bloat an apk contains though.
[+] theandrewbailey|8 years ago|reply
> Beautiful. Our APK weighs in at approximately 1.5Mb.

WTF? This Hello World app is 1.5 MB, but MS Paint, a program with much richer functionality, is not even a third of that! I know that MS Paint is ancient, but if it takes 1.5 MB by default to put text on a screen, multiple levels of something have failed, especially when it can squeeze down to <100 KB without too much trouble.

[+] kogus|8 years ago|reply
I don't necessarily disagree, but MS Paint on my Windows 10 machine weighs in at 6.5Mb. Notepad++ is just 2.5Mb though. And the Windows Media Player is just 163k.
[+] duiker101|8 years ago|reply
Thing is, space and bandwidth are way cheaper now compared to the age of MS Paint. 1Mb, 10Mb, even 40 or 50 don't do much difference to most users but they can make things easier to develop/maintain/whatever. Which in the end could save a lot of money to a company.