在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