Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reducing APK size by re-zipping its content

Tags:

android

apk

I have a pretty large apk file, and I'm trying to reduce its size. Already used all the common techniques, such as Proguard and image compression. Still, the apk is quite large - about 25mb.

Wikipedia says that:

APK files are a type of archive file, specifically in zip format packages based on the JAR file format, with .apk as the filename extension.

I've recently noticed that if I'll unzip the apk (Android Studio's artifact output), re-zip it using 7-Zip and sign it, then the size magically decreases by 2.5mb (to ~22.5mb). I'm able to upload it to Play, install and run it without an issue.

And here're my questions:

  • Is there any data that wiped during unzip & rezip process?
  • If no, why aapt (the one that Android Studio uses) packages files in so inefficient manner?
  • If yes, what data is being wiped (please post some links where I could read more about it)? What could go wrong if I'll use this method?

Thanks!


Edit [5/13/2015]:

Compressing the APK contents worked well for me. However, I had to be cautious with raw resources (typically placed under res/raw). For example, invoking Resources#openRawResourceFd with a compressed resource as parameter will end with the following exception:

java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed

Therefore, remember to exclude raw resources from compression.

like image 274
Alex Lipov Avatar asked Aug 21 '14 11:08

Alex Lipov


2 Answers

I'm able to upload it to Play, install and run it without an issue.

Only on the devices that you tried. I suspect, for example, that you did not try an API Level 1 device.

Is there any data that wiped during unzip & rezip process?

We have no way of answering that question. The only person who can answer that question is you, as you are the one who did your specific "unzip & rezip process". You should be able to analyze your two ZIP files and see where the differences are, such as higher compression ratios on certain file types, files that got lost by the way you ran your "rezip process", etc.

In general, the only thing that should be lost would be any zipalign-ing, if you did not reapply that yourself.

If no, why aapt (the one that Android Studio uses) packages files in so inefficient manner?

Size is not the only consideration. Speed of access is another, as many things (e.g., resources, assets) are kept in the APK file and read out of there on the fly as needed. Memory consumption for the decompression logic is yet another consideration.

Android devices, particularly early ones, have many constraints, disk space being but one of them. Even though some of these constraints have been relaxed as hardware has advanced, the build tools are dedicated to backwards compatibility -- you should be able to write an app today that can run on an API Level 1 device, for example. That puts constraints on the tools in terms of how they can change over time.

What could go wrong if I'll use this method?

Your app may not work on Android devices, where their runtimes are set up making certain assumptions about the APK ZIP compression algorithms use. Ideally, your app will run fine everywhere. At minimum, you would want to test your app on every API level that you support -- older API levels may be somewhat more likely to "cut corners" and make assumptions that your approach will invalidate.

like image 183
CommonsWare Avatar answered Nov 10 '22 10:11

CommonsWare


Assuming you are forcing 7zip to use its zip compatible mode (-tzip) then this is an entirely valid operation (though as @CommonsWare notes, there is a tiny possibility that you are opening yourself up to some buggy implementations of the zip unpacking routine on some phones).

The reason that you are able to get a size reduction are twofold:

  • 7zip has a better compressor, that uses more CPU on the compression to come up with a perfectly compatible but more compressed representation
  • aapt which is traditionally used to do the compression/packaging of the Android file has a long list of filetypes (such as jpg, png, mp3) that it simply does not try to compress, on the grounds that these filetypes already have internal compression. Even so, there's often a few percent gain to be had by compressing them inside the apk file
like image 33
zmarties Avatar answered Nov 10 '22 11:11

zmarties