Android apps are typically written in Java* because of its elegant object-oriented design and the fact that the Android Software Development Kit (Android SDK) provides cross-platform features in Java. At times, however, developers need to use Android’s native interface, especially if memory management and performance are critical issues. Android’s native interface is provided through the Native Development Kit (NDK), which supports native development in C/C++.
There are many NDK apps on the Google software market. To reduce package size, some ISVs release a single APK but not a FAT APK (a single APK contains either an ARM* or an x86 library, while a FAT APK has both). FAT APKs have advantages over single APKs. They are easier for end users to access and the libraries aren’t overlapped during application updating. Developers are, therefore, encouraged to make FAT APKs for the x86 Android software ecosystem. But how can developers mitigate large FAT APK file sizes?
To solve the FAT APK size problem, the author has developed a native library compression SDK. The basic idea uses the Lempel–Ziv–Markov chain algorithm (LZMA) (LZMA SDK (Software Development Kit)) to compress native libraries. Google uses Zip to compress all of the content, and while Zip is fast, its compression rate is lower than LZMA. LZMA is especially good for compressing the large dictionary files found in native libraries. The following graph shows the difference in file sizes after performing compressions with Zip and LZMA.
Figure 1: Size comparison of a file after being compressed with Zip* and LZMA1
Figure 2: Size comparison of multiple files (same CPU architecture) after being compressed with Zip* and LZMA1
Figure 3: Size comparison of multiple files (different CPU architecture) after being compressed with Zip* and LZMA1
Figure 4: Size comparison of three identical files after being compressed with Zip* and LZMA1
From the four charts above, we may conclude that LZMA can reduce the redundancy between the files. In the extreme (three identical files), LZMA can get a higher compression rate than Zip. This feature is particularly suitable for compressing native libraries. Generally, a native library will use the same code to get “armeabi”,”armeabi-v7a”,”x86” or even “mips” libraries, and for “armeabi-v7a” there is ARM NEON* and non-NEON code as well. These libraries have redundancies due to the same source code. Even with different architecture, for example,libffmpeg_armv7_vfpv3.so and libffmpeg_x86.so, when one is ARMEABI and the other is x86, the compression rate is 40%, while for a single file, the rate is only 20%.
The native library compression SDK, the author developed, can help app developer to integrate the LZMA native library compression to obtain smaller files. The core idea of this SDK is to compress the entire native library into theasserts folder as follows.
The API in this SDK is very simple. On the first run of this application, the code extracts the entire native library from the asserts folder.
static boolean NewInstance(Context cont,Handler hdl,boolean showProgress)
static DecRawso GetInstance()
String GetPath(String libname)
It is recommended that app developers should modify the source code and add only NewInstance when the application starts, then change system.loadlibrary(***) to system.load(DecRawso . GetInstance ().GetPath(***)). After these minor changes, the APK will be smaller yet run the same as before.
If developers can ensure enough delay from the calling of NewInstance to the first loading of native library, they should call (NewInstance (cont,null,false)) without the Handler. Otherwise, a Handler should be passed to receive the “decode end” asynchronous message.
The author integrated this SDK into MoboPlayer* on an Intel® Atom™ Z2760 processor-based tablet (codenamed Clover Trail). The code calls NewInstance in the synchronization method when users start the app and the splash screen is displayed. Calling NewInsance is transparent to the end user since the decoding is done in the background. The following chart shows the compression result.
Table 5: MoboPlayer* FAT APK size compression1
Besides the LZMA compression, this SDK provides additional functions to encourage developers to include an x86 native library with the following:
For more such Android resources and tools from Intel, please visit the Intel® Developer Zone