The previous recipe discussed how to port a library as a
shared library module with the libbmp
library as an example. In this recipe, we will demonstrate how to port the libbmp
library as a static library.
Readers are recommended to read the Building an Android NDK application at the command line recipe in Chapter 3, Build and Debug NDK Applications, before going through this one.
The following steps describe how to create our sample Android project that demonstrates porting the libbmp
library as a static library:
PortingStatic
with native support. Set the package name as cookbook.chapter8.portingstatic
. Please refer to the Loading native libraries and registering native methods recipe of Chapter 2, Java Native Interface, if you want more detailed instructions.MainActivity.java
under the cookbook.chapter8.portingstatic
package. This Java file simply loads the shared library PortingStatic
, and calls the native method naCreateABmp
.libbmp
library and make changes.Android.mk
file under the libbmp
folder to compile libbmp
as a static library libbmp.a
. The content of this Android.mk
file is as follows:LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libbmp LOCAL_SRC_FILES := bmpfile.c include $(BUILD_STATIC_LIBRARY)
libbmptest
under the jni
folder. Add the mylog.h
and PortingStatic.c
files to it. Note that the code for it is the same as the naCreateABmp
method in previous chapter except that the .bmp
file name is changed from test_shared.bmp
to test_static.bmp
.Android.mk
file under the libbmptest
folder to compile the PortingStatic.c
file as a shared library libPortingStatic.so
. The content of this Android.mk
file is as follows:LOCAL_PATH := $(call my-dir include $(CLEAR_VARS) LOCAL_MODULE := PortingStatic LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libbmp/ LOCAL_SRC_FILES := PortingStatic.c LOCAL_STATIC_LIBRARIES := libbmp LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)
Android.mk
file under the jni
folder with the following content:LOCAL_PATH := $(call my-dir) include $(call all-subdir-makefiles)
WRITE_EXTERNAL_STORAGE
permission to the AndroidManifest.xml
file as follows:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
test_static.bmp
should be created at the sdcard
folder of the Android device. We can use the following command to get the file:$ adb pull /sdcard/test_static.bmp .
This file is the same as the test_static.bmp
file used in the previous recipe.
In the sample project, we build libbmp
as a static library libbmp.a
, which can be found under obj/local/armeabi/ folder
. We called the functions defined in libbmp
in the native code PortingStatic.c
.
A static library is simply an archive of object files compiled from the source code. They are built as files ending with ".a
" suffix at Android NDK. A static library is copied into a targeted executable or library at build time by a compiler or linker. At Android NDK, static libraries are only used to build the shared libraries, because only shared libraries are packaged into the apk
file for deployment.
Our sample project builds a static library libbmp.a
and a shared library libPortingStatic.so
. The libPortingStatic.so
shared library is located under the libs/armeabi
folder, and will be copied to the application's apk
file. The libbmp.a
library is used to build the libPortingStatic.so
shared library. If you examine the symbols of the libPortingStatic.so
library with the
Eclipse project explorer, you will find that the symbols for the functions defined at libbmp
are included. This is shown in the following screenshot:
The functions bmp_create
, bmp_destroy
, and so on, are defined in libbmp
and are included in the shared library libPortingStatic.so
.
In our Java code, we will need to load the shared library with the following code:
static { System.loadLibrary("PortingStatic"); }
Understand the Android.mk files: The previous recipe already describes most of the predefined variables and macros used in the three Android.mk
files in this recipe. Therefore, we only cover the ones that we have not seen in the previous recipe:
BUILD_STATIC_LIBRARY
: The variable points to a build script which will collect the information about the module and determine how to build a static library from the sources. The module built is usually listed in LOCAL_STATIC_LIBRARIES
of another module. This variable is normally included in Android.mk
as follows:include $(BUILD_STATIC_LIBRARY)
In our sample project, we include this variable in the Android.mk
file, under jni/libbmp
folder.
LOCAL_STATIC_LIBRARIES
: This is a module description variable, which provides a list of static libraries the current module should be linked to. It only makes sense in shared library modules.In our project, we used this variable to link to the libbmp.a
static library, as shown in the Android.mk
file under the jni/libbmptest/
folder.
LOCAL_STATIC_LIBRARIES := libbmp
LOCAL_WHOLE_STATIC_LIBRARIES
: This is a variant of the LOCAL_STATIC_LIBRARIES
variable. It indicates that the static libraries listed should be linked as whole archives. This will force all object files from the static libraries to be added to the current shared library module.Static versus shared: Now that you have seen how to port an existing library as either a static or shared library, you may ask which one is better. The answer, as you might have expected, depends on our needs.
When you port a big library and only use a small portion of the functions provided by the library, then a static library is a good option. The Android NDK build system can resolve the dependencies at build time and only copy the parts that are used in the final shared library. This means a smaller library size and subsequently smaller apk
file size.
When you port a library, which will be used by several Android apps, then shared library is a better choice. Suppose you want to build two Android apps, a video player and a video editor. Both apps will need a third-party codec
library, which you can port to Android with NDK. In this case, you can port the library as a shared library in a separate apk
file (for example, MX Player puts the codecs
library in separate apk
files) and the two apps can load the same library at runtime. This means that the users only need to download the library once to use both the apps.
Another case in which you may need the shared library is that a library L
is used in multiple shared libraries. If L
is a static library, each
shared library will include a copy of its code and cause problems because of code duplication (for example, duplicated global variables).
We have actually ported a library as a static library with Android NDK build system before. Recall how we ported libpng
as a static library in the Managing assets at Android NDK recipe in Chapter 5, Android Native Application API.