#SmallerAPK, Part 8: Native libraries, open from APK

Adding even a single native library can contribute quite significantly to your app’s size. If your app uses any native libraries (i.e. there are .so files in your APK), this article is for you.

There are various techniques and flags for C/C++ compilation that can make your .so files smaller, but I will not be discussing native builds in this article as it’s a broad and very advanced topic, with each particular case requiring special treatment. Besides, it might happen that you get compiled .so files only and without access to the source code there’s not much you can do about their size. Instead, I will show you this one weird trick that cuts disk space usage in half! No, really… read on :)

In Part 1 of this series, I mentioned that the biggest waste of space from having native libraries comes from the fact that compressed .so files are copied out from the APK at install time into a user’s /data partition. The originals are never deleted from the APK (because we can’t delete files from signed APKs, remember?). Thus, they take up twice the amount of space on the device.

Starting with Android 6.0 (Marshmallow), there is a new flag that you can set on your <application>:

AndroidManifest.xml

<application
android:extractNativeLibs=”false”
...
>

This will essentially prevent the system from creating a second copy of the .so files and fix the System.loadLibrary call so it’s able to find and open native libs straight from the APK, no code changes on your part required.

There are some important preconditions for that to work though and that’s where things get more complicated:

  1. The .so files inside the APK cannot be compressed — they must be stored.
  2. The .so files must be page aligned using zipalign -p 4

Starting from Android Studio 2.2 Preview 2 and newest build tools, the build process will automatically store native libraries uncompressed and page aligned in the APK.


Let’s look at what effect on file and download sizes keeping native libraries uncompressed has:

Initial download size

Should be roughly the same. How is that possible? The Play Store actually uses its own compression when sending APK files to users’ devices. Depending on the compressibility of your particular library, the download size might be roughly the same or just slightly larger.

Update size

Should be smaller. Play Store uses a mechanism called “delta updates” to deliver new versions of apps to existing users. It calculates the difference between the new APK and the APK that’s installed on a device and only sends the binary difference needed to reconstruct the final APK on the device.

Having the native libraries uncompressed actually helps the algorithms used by Play calculate a more optimal (i.e. smaller) delta. These delta patch files will additionally be compressed for delivery.

On-device size

Total size on-device will be smaller on Marshmallow and above. However, older Android versions will not recognize the android:extractNativeLibs flag and always copy out the .so files. The amount of additional space wasted because of using this technique is the difference between a compressed and uncompressed .so file.