JNI:Java Native Interface,即Java本地接口,使Java与其他类型的语言进行交互,和C/C++交互的比较多。JNI属于Java的一部分,是JDK的组成部分,和Android关系不大,但是Android中核心的业务或高性能的功能都是C/C++开发的,比如游戏渲染、音视频编解码等,所以对于Android开发,JNI也是需要了解的。Android中并不是直接和C/C++打交道,是和.so(动态库),.a(静态库)文件打交道。
Android中使用JNI需要提前安装NDK,NDK(Native Development Kit)是后台Android平台提供的开发工具包,把JNI、gcc、g++…等都封装进入了,方便开发者开发。
project:
CMakeLists.txt:
native-lib.cpp
和常规的Android项目比,大部分都一样,有些配置文件不同,还多了cpp目录,cpp目录下native-lib.cpp文件就是Java调用C/C++的地方。
CMakeLists.txt是CMake的组态档,组态档是用一种建构软件专用的特殊编程语言写的CMake脚本,CMake是CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。
java中的属性和方法在C/C++中不能直接使用,需要按照一定的规则进行转换。
java | C/C++ |
---|---|
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | J |
float | F |
double | D |
void | V |
object obj | Lobj |
int[] | [I |
void name(double b) | (D) V |
// Used to load the 'jni' library on application startup.
static {
System.loadLibrary("jni");
}
如果没有设置库名称,可以直接使用文件名。
static {
System.loadLibrary("native-lib");
}
在MainActivity中创建native方法。
/**
* A native method that is implemented by the 'jni' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
native-lib.cpp中需要使用c++实现创建的native方法。
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jni_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
细节解读:
Java:
private String name;
// native方法,修改name字段
public native void updateName();
native-lib.cpp中:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_jni_MainActivity_updateName(JNIEnv *env, jobject thiz) {
// 拿到MainActivity
jclass mainActivityCls = env->GetObjectClass(thiz);
// 获取属性名称及类型
jfieldID name_fid = env->GetFieldID(mainActivityCls,"name", "Ljava/lang/String;");
// 设置被修改的Java的属性的值
jstring value = env->NewStringUTF("JNI测试");
// 赋值
env->SetObjectField(thiz,name_fid,value);
}
Java:
private int num01 = 1;
private int num02 = 2;
// java方法
public int add(int num1,int num2){
return num1 + num2;
}
// native方法
public native int addNum();
native-lib.cpp:
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_jni_MainActivity_addNum(JNIEnv *env, jobject thiz) {
// 拿到MainActivity.class
jclass mainActivityCls = env->GetObjectClass(thiz);
// 获取方法
jmethodID add_mid = env->GetMethodID(mainActivityCls,"add", "(II)I");
// 调用方法
env->CallIntMethod(thiz,add_mid,100,200);
}