在Android中的JNI機制主要用於Java對C/C++調用,爲了讓這種調用最爲簡單,Google設計了一套完整的遊戲規則,當全部的接口文件都按照這套規則去設計的時候,開發着在調用的時候纔會最簡單。這套標準簡單來講包括一個Java層的接口文件,一個JNI實現的頭文件和一個根據JNI標準編寫的cpp文件編譯出的動態連接庫組成,以下:
java
public class JNIUtils { public static native int addFromJNI(int a, int b); }
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> #include "JniTest.h" /* Header for class com_wujian_jnidemo_JNIUtils */ #ifndef _Included_com_wujian_jnidemo_JNIUtils #define _Included_com_wujian_jnidemo_JNIUtils #ifdef __cplusplus extern "C" { #endif /* * Class: com_wujian_jnidemo_JNIUtils * Method: addFromJNI * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_wujian_jnidemo_JNIUtils_addFromJNI (JNIEnv *, jclass, jint, jint); #ifdef __cplusplus } #endif #endif
對應的還會有一個cpp文件實現這個頭文件中的函數ide
#include "com_wujian_jnidemo_JNIUtils.h" /* * Class: com_wujian_jnidemo_JNIUtils * Method: addFromJNI * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_wujian_jnidemo_JNIUtils_addFromJNI (JNIEnv *, jclass, jint a, jint b) { return a+b; }
這個cpp最終根據平臺編譯出對應的動態連接庫這個庫的名字是本身在cmakelist中定義的函數
相對應的還有不按照JNI標準編譯的庫文件,這些動態連接庫每每是各個平臺共用的,不必定只是在Android中被使用,so文件所對應的cpp文件和頭文件徹底是按照標準的cpp或者c語言格式編寫的,好比寫一個很簡單的加法的函數並吧這個函數編譯成動態連接庫,代碼以下:ui
//JniTest.h #include<stdio.h> int funcAdd(int a, int b); //JniTest.c #include"JniTest.h" int funcAdd(int a, int b) { return a+b; }
建立一個名叫jnitest的文件夾中,而後在jnitest下建立一個名叫jni的子目錄,將這兩個文件拷貝到jni下面,而後在這個目錄中建立兩個文件,分別爲Android.mk和Application.mk命令行
#Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := jnitest LOCAL_SRC_FILES := JniTest.c # 添加對log庫的支持 LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog # 注:若生成static的.a,只需添加 LOCAL_LDLIBS:=-llog include $(BUILD_SHARED_LIBRARY) LOCAL_PATH := $(call my-dir) #Application.mk APP_ABI := all APP_BUILD_SCRIPT := Android.mk
此時jni目錄下應該有這些文件
在jni目錄下啓動terminal或者命令行,使用ndk-build編譯(ndk命令的配置省略),編譯完成以下圖,而且會在jni的同級目錄下建立一個libs的目錄,裏面就是各個平臺對應的動態連接庫,文件名叫libjnitest.so
設計
libjnitest.so是一個典型的非JNI標準的動態連接庫,他沒有對應的Java接口,沒有對應的JNI頭文件,如今不少第三方的SDK都是提供這種庫文件,同時還會提供一個對應的頭文件至關於上述的JniTest.h,爲了能在JNI開發中正常調用這種ku文件中的方法,通常須要在他的外面再封裝一層JNI,經過JNI去調用這個庫中的方法,而後本身向java層提供調用的接口code