Sunday, June 5, 2016

Android studio - NDK - include and use .so library

Compile library (.so)
Create jni and jniLibs folder. The structure of your project would be:

PROJECTNAME
|-app
   |-src
      |-main
         |-jni
         |-jniLibs

Create native code and make files:
PROJECTNAME
|-app
   |-src
      |-main
         |-jni
            |-Android.mk
            |-Application.mk
            |-setenv.c


Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := native  // module name, this name is just an example
LOCAL_SRC_FILES := setenv.c // your C code
include $(BUILD_SHARED_LIBRARY)

Application.mk
APP_ABI := all

APP_BUILD_SCRIPT := Android.mk

setenv.c
#include <jni.h>
#include <stddef.h>
#include <stdlib.h>

JNIEXPORT jint JNICALL Java_hcmut_controller_FcamController_setenv(JNIEnv* env, jclass clazz, jstring key, jstring value, jboolean overwrite)
{
    char* k = (char *) (*env)->GetStringUTFChars(env, key, NULL);
    char* v = (char *) (*env)->GetStringUTFChars(env, value, NULL);
    int err = setenv(k, v, overwrite);
    (*env)->ReleaseStringUTFChars(env, key, k);
    (*env)->ReleaseStringUTFChars(env, value, v);
    return err;

}

* Note: function name in .c code follows the naming convention:
Java_your_package_ClassName_functionname(.......)

PROJECTNAME
|-app
   |-src
      |-main
         |-hcmut
            |-controller
               |-FcamController.java

associated with Java_hcmut_controller_FcamController_setenv

Jump to the folder containing Application.mk file and execute the following command:
$ cd "~/Project/Android/CrowdCounting/app/src/main/jni"
$ ~/android-ndk/ndk-build NDK_APPLICATION_MK=./Application.mk
--> It will compile and create obj folder in the same level with jni folder.


Use library
Copy the folders in obj/local/* to jniLibs
|-app
   |-src
      |-main
         |-jni
         |-jniLibs
            |-arm64-v8a
            |-armeabi
            |-armeabi-v7a
            |-mips
            |-mips64
            |-x86
            |-x86_64

To use the native library, we load the library and declare the library's method
PROJECTNAME
|-app
   |-src
      |-main
         |-hcmut
            |-controller
               |-FcamController.java

FcamController.java
static {
        System.loadLibrary("native");
}
private static native int setenv(String key, String value, boolean overwrite);

* You can check the library whether it is included by opening .apk file with Archive Manager (Linux)


Other way to add library (.so)
Create a .zip file with the structure:
mylib.zip
|-lib
   |-armeabi
      |-libnative.so
   |-armeabi-v7a
      |-libnative.so
   |-x86
      |-libnative.so
    ...

Then change the file type from mylib.zip to mylib.jar

Put mylib.jar in libs folder
PROJECTNAME
|-app
   |-libs
      |-mylib.jar

Modify dependencies in build.gradle
PROJECTNAME
|-app
   |-libs
   |-build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.1'
}

References:
https://software.intel.com/en-us/articles/building-an-android-command-line-application-using-the-ndk-build-tools
http://stackoverflow.com/questions/16683775/include-so-library-in-apk-in-android-studio
https://groups.google.com/forum/?fromgroups#!topic/adt-dev/nQobKd2Gl_8

No comments:

Post a Comment