Using a library in multiple projects with import-module

You may often need to use a library in multiple projects. You can put the library in each of the project's jni folders and build them separately. However, it is troublesome to maintain multiple copies of the same library. For example, when there is a new release of the library and you want to update the library, you will have to update each copy of the library.

Fortunately, Android NDK provides a feature to allow us maintain a library module outside a NDK project's main source tree and import the module with simple commands in the Android.mk file. Let's discuss how to import a module in this recipe.

How to do it...

The following steps describe how to declare and import a module outside of a project's jni folder:

  1. Create an Android application named ImportModule with native support. Set the package name as cookbook.chapter8.importmodule. Please refer to the Loading native libraries and registering native methods recipe of Chapter 2, Java Native Interface for more detailed instructions.
  2. Add a Java file MainActivity.java under the cookbook.chapter8.importmodule package. This Java file simply loads the shared library ImportModule, and calls the native method naCreateABmp.
  3. Download the libbmp library from http://code.google.com/p/libbmp/downloads/list and extract the archive file. Create a folder named modules under the project and a folder libbmp-0.1.3 under the modules folder. Copy the src/bmpfile.c and src/bmpfile.h files from the extracted folder to the libbmp-0.1.3 folder.
  4. Follow step 3 of the Porting a library as shared library module with Android NDK build system recipe to update src/bmpfile.h.
  5. Create an Android.mk file under the libbmp-0.1.3 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
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
    include $(BUILD_STATIC_LIBRARY)
  6. Add the mylog.h and ImportModule.c files to it. ImportModule.c implements the native method naCreateABmp.
  7. Create an Android.mk file under the jni folder to compile ImportModule.c as a shared library libImportModule.so. The content of this Android.mk file is as follows:
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE    := ImportModule
    LOCAL_SRC_FILES := ImportModule.c
    LOCAL_LDLIBS := -llog
    LOCAL_STATIC_LIBRARIES := libbmp
    include $(BUILD_SHARED_LIBRARY)
    $(call import-add-path,$(LOCAL_PATH)/../modules)
    $(call import-module,libbmp-0.1.3)
  8. Add the WRITE_EXTERNAL_STORAGE permission to the AndroidManifest.xml file as follows:
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  9. Build and run the Android project. A bitmap file test_bs_static.bmp should be created at the sdcard folder of the Android device. You can use the following command to get the file:
    $ adb pull /sdcard/test_im.bmp .

    The file is the same as test_static.bmp, as shown in the Porting a library as shared library module with Android NDK build system recipe of this chapter.

How it works...

In your sample project, you created a module outside the jni folder of the project and then imported the module for building the shared library libImportModule.so. The following steps should be performed when you declare and import a module:

  1. Declare the import module: There is nothing special in declaring an import module. Since an import module is usually used by multiple NDK projects, it is a good practice to export the header files (with LOCAL_EXPORT_C_INCLUDES), compiler flags (LOCAL_EXPORT_CFLAGS or LOCAL_EXPORT_CPPFLAGS), and linker flags (LOCAL_EXPORT_LDLIBS) when declaring the import module.

    In our sample project, you declared an import static library module libbmp.

  2. Decide the place to put the import module: The Android NDK build system will search the paths defined in NDK_MODULE_PATH for the import modules. By default, the sources folder of the Android NDK directory is appended to NDK_MODULE_PATH. Therefore, you can simply place our import module folder under the sources folder and the Android NDK build system will be able to find it.

    Alternatively, you can place the import module folder anywhere and append the path to NDK_MODULE_PATH. In our sample project, place the import the libbmp module in the modules folder.

  3. Append the import path: This is not needed when placing the import module folder under the sources directory of Android NDK. Otherwise, you will need to tell the Android NDK build system where the import modules are, by appending the path to NDK_MODULE_PATH. The import-add-path macro is provided by NDK to help you to append the path.

    In your sample project, you appended the modules folder to NDK_MODULE_PATH with the following line at jni/Android.mk:

    $(call import-add-path,$(LOCAL_PATH)/../modules)
  4. Import the module: Android NDK provides a macro import-module to import a module. This macro accepts a relative path to the import module's folder where the Android.mk file of the import module is located. The Android NDK build system will search for all the paths defined at NDK_MODULE_PATH for the import module.

    In your sample project, you imported the module with the following line at the jni/Android.mk file:

    $(call import-module,libbmp-0.1.3)

    The NDK build system will search for the libbmp-0.1.3/Android.mk file at all NDK_MODULE_PATH directories for the import modules.

  5. Use the module: Using an import module is just like using any other library module. You will need to link to the library by listing it at LOCAL_STATIC_LIBRARIES for the static library import module and LOCAL_SHARED_LIBRARIES for the shared library import module.

For more information about how to import modules, you can refer to docs/IMPORT-MODULE.html at Android NDK.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset