Androidstudio2.2.2 + NDK R13
新建Mudle 名为JNI_Test,MainActivity中声明 native 方法,如下:
private static native String getStringFromJNI();
并且在onCreate()方法之前声明要导入的so库文件,即java代码调用native方法时要引用的so动态库文件。如下:
static { System.loadLibrary("getString"); }
点击Build ->Make Module"JNI_Test" 或者是Make Project 编译Module,即java文件编译为class文件,编译成功后如图下:
在终端terminal窗口使用javah 命令编译上一步生成的MainActivity.class,以产生声明有 native 方法的java文件对应的C头文件。命令如下:
首先跳到 main 文件夹:cd D:\WorkPlace\AndroidStudio\jni_test\src\main
执行编译命令:
javah -d jni -classpath E:\AndroidStudio_SDK\platforms\android-23\android.jar;..\..\build\intermediates\classes\debug com.example.jni_test.MainAct
ivity
详解:javah -d(编译命令)
jni 生成一个文件夹名为jni的文件夹,用于存放生成的头文件。
E:\AndroidStudio_SDK\platforms\android-23\android.jar 编译当前module的SDK版本的jar文件。
; 分号,用于与后面的class文件隔开。
..\..\build\intermediates\classes\debug com.example.jni_test.MainActivity 前半部分指向module编译生成的class文件路径,后半部分指向生成C头文件的class文件。
生成头文件如图:
头文件内容为:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_jni_test_MainActivity */ #ifndef _Included_com_example_jni_test_MainActivity #define _Included_com_example_jni_test_MainActivity #ifdef __cplusplus extern "C" { #endif #undef com_example_jni_test_MainActivity_BIND_ABOVE_CLIENT #define com_example_jni_test_MainActivity_BIND_ABOVE_CLIENT 8L #undef com_example_jni_test_MainActivity_BIND_ADJUST_WITH_ACTIVITY #define com_example_jni_test_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L #undef com_example_jni_test_MainActivity_BIND_ALLOW_OOM_MANAGEMENT #define com_example_jni_test_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L #undef com_example_jni_test_MainActivity_BIND_AUTO_CREATE #define com_example_jni_test_MainActivity_BIND_AUTO_CREATE 1L #undef com_example_jni_test_MainActivity_BIND_DEBUG_UNBIND #define com_example_jni_test_MainActivity_BIND_DEBUG_UNBIND 2L #undef com_example_jni_test_MainActivity_BIND_IMPORTANT #define com_example_jni_test_MainActivity_BIND_IMPORTANT 64L #undef com_example_jni_test_MainActivity_BIND_NOT_FOREGROUND #define com_example_jni_test_MainActivity_BIND_NOT_FOREGROUND 4L #undef com_example_jni_test_MainActivity_BIND_WAIVE_PRIORITY #define com_example_jni_test_MainActivity_BIND_WAIVE_PRIORITY 32L #undef com_example_jni_test_MainActivity_CONTEXT_IGNORE_SECURITY #define com_example_jni_test_MainActivity_CONTEXT_IGNORE_SECURITY 2L #undef com_example_jni_test_MainActivity_CONTEXT_INCLUDE_CODE #define com_example_jni_test_MainActivity_CONTEXT_INCLUDE_CODE 1L #undef com_example_jni_test_MainActivity_CONTEXT_RESTRICTED #define com_example_jni_test_MainActivity_CONTEXT_RESTRICTED 4L #undef com_example_jni_test_MainActivity_MODE_APPEND #define com_example_jni_test_MainActivity_MODE_APPEND 32768L #undef com_example_jni_test_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING #define com_example_jni_test_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L #undef com_example_jni_test_MainActivity_MODE_MULTI_PROCESS #define com_example_jni_test_MainActivity_MODE_MULTI_PROCESS 4L #undef com_example_jni_test_MainActivity_MODE_PRIVATE #define com_example_jni_test_MainActivity_MODE_PRIVATE 0L #undef com_example_jni_test_MainActivity_MODE_WORLD_READABLE #define com_example_jni_test_MainActivity_MODE_WORLD_READABLE 1L #undef com_example_jni_test_MainActivity_MODE_WORLD_WRITEABLE #define com_example_jni_test_MainActivity_MODE_WORLD_WRITEABLE 2L #undef com_example_jni_test_MainActivity_DEFAULT_KEYS_DIALER #define com_example_jni_test_MainActivity_DEFAULT_KEYS_DIALER 1L #undef com_example_jni_test_MainActivity_DEFAULT_KEYS_DISABLE #define com_example_jni_test_MainActivity_DEFAULT_KEYS_DISABLE 0L #undef com_example_jni_test_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL #define com_example_jni_test_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L #undef com_example_jni_test_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL #define com_example_jni_test_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L #undef com_example_jni_test_MainActivity_DEFAULT_KEYS_SHORTCUT #define com_example_jni_test_MainActivity_DEFAULT_KEYS_SHORTCUT 2L #undef com_example_jni_test_MainActivity_RESULT_CANCELED #define com_example_jni_test_MainActivity_RESULT_CANCELED 0L #undef com_example_jni_test_MainActivity_RESULT_FIRST_USER #define com_example_jni_test_MainActivity_RESULT_FIRST_USER 1L #undef com_example_jni_test_MainActivity_RESULT_OK #define com_example_jni_test_MainActivity_RESULT_OK -1L /* * Class: com_example_jni_test_MainActivity * Method: getStringFromJNI * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_jni_1test_MainActivity_getStringFromJNI (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
接下来要在C文件里实现 native 方法了,在生成的jni文件夹内新建一个C文件,命名随意,我在这里命名为main.c 。把之前编译生成的头文件包括进来,并且把头文件中声明的方法给予实现,即把该方法copy过来粘贴到c文件里并且实现。
在该module的build.gradle文件的defaultConfig节点加入
ndk{ moduleName "getString" abiFilters "armeabi", "armeabi-v7a", "x86" }
moduleName 为指定生成的so文件名。
abiFilters 指定支持的ABIs(CPU架构)。
接下来再点击Build ->Make Module"JNI_Test" 或者是Make Project 编译Module,就会有so文件生成如图:
至此NDK开发实现完毕,直接把module运行到Android设备上,如图:
Android的JNI开发成功实现!!!