JNI,即Java Native Interface,Java本地接口,用于与其他语言交互,说白了就是翻译,把JAVA语言翻译成其他语言,或者把其他语言翻译成JAVA语言,拿C或C++举个例子:
Java想调C/C++里面的方法,由于语言不通,它们没办法交互,这时,JNI来了,JNI说,我来当你们的翻译,于是乎,Java调用JNI中的方法,而JNI调用C/C++中的方法。
但是JNI的调用不是随随便便的,它们之间存在一个对应关系。
(1)数据类型
Java类型 | JNI类型 | 本地类型 | C/C++类型 | 描述 |
boolean | jboolean | uint8_t | unsigned char | 无符号8位 |
byte | jbyte | char | char | 有符号8位 |
char | jchar | uint16_t | unsigned short | 无符号16位 |
short | jshort | int16_t | short | 有符号16位 |
int | jint | int32_t | int | 有符号32位 |
long | jlong | int64_t | long long | 有符号64位 |
float | jfloat | float | float | 32位 |
double | jdouble | double | double | 64位 |
void | void | void | void | N/A |
(2)引用类型
Java类型 | JNI类型 | ||
所有实例引用 | jobject | ||
java.lang.String | jstring | ||
java.lang.Throwable | jthrowable | ||
java.lang.Class | jclass | ||
Ocject[ ] | jobjectArray | ||
基本类型[ ] | jxxxArray |
OK,简单介绍完JNI的一些知识,下面我们实践一波。
先说一下NDK的开发流程:
- 在Java中写native代码
- 写JNI方法
- 写C/C++方法
- 配置动态链接库名称
- 加载动态链接库
- 调用方法
OK,实践
1.Android Studio新建一个native工程
划到最下面,选择native C++ ,下一步
填好工程名Name、包名Package name、工程保存路径Save location,语言Language选Java ,最小SDK默认即可,下一步
C++ 标准 默认,finish
自此,native工程创建完毕。观察工程可以看到,AS默认帮我们创建了一个示例:
MainActivity中声明native方法,加载动态链接库,并调用native方法。
native-lib.cpp中则声明JNI方法,记住cpp文件中一定要包含#include <jni.h>
native-lib.cpp则通过CMake编译,库的名称,编译成静态库还是动态库,C++源文件
通过它的示例,我们可以创建一个:
1.新建一个Java 类,类名*取,我这边类名为JNI
2.声明native方法
public class JNI {
public native void funtion1();
}
声明完之后发现它爆红,那是因为JNI中没有相对应的方法。
3.鼠标光键放在方法名上,点击鼠标左键,创建相对应的JNI方法
这时在native-lib.cpp中自动定义了一个空的JNI方法
解释一下JNI方法名的含义:
以Java开头,短下划线连接包名,类名,Java中的方法名,即Java_包名_类名_方法名,JNI类中funtion1的返回值为void,那么JNI方法的返回值也要对应。
接下来是JNI方法里面的参数JNIEnv *
指针,它相当于环境变量,提供了JNI中的一系列操作的接口函数。jobject 其实就是Java层的实例,说白了就是谁调用这个方法,它就是谁的实例,当前就是JNI。我们操作jobject其实就是操作java层的实例,我们要操作一个实例,无非是两点:(1)获取(get)或设置(set)成员变量(field)的值;(2)调用成员方法(method)。至于如何获取成员变量和成员方法,我们下次再详细说。
4.实现JNI方法
未完待续。。。