简介:
JNI的全称就是Java Native Interface,Java本地接口。
作用:使得Java 与 本地其他类型语言(如C、C++)交互
注意:JNI开发前提是要引入jni.h头文件,这个文件Android NDK目录下面
示例: #include<jni.h>
- 通过javac和javah编译出一个your_jni.h文件默认是包含#include<jni.h>的。所以在实现your_jni.h文件中的方法时只需要#include<your_jni.h>即可,无需在重复#include<jni.h>。
- 若直接定义c/c++文件,需要#include<jni.h>。
一、NDK环境配置
1、现在NDK版本配置环境变量
、
2、AndroidStudio配置NDK路径
在local.properties文件中配置路径
3、在app build.gradel中添加ndk节点
defaultConfig {
.......
ndk{
//模块名称,编译后的.so库文件名称
moduleName "HelloJni"
//使用stl标准库(默认情况下JNI中无法使用STL标准库)
stl "stlport_static"
//log 表示加入Android的调试日志,只要导入#include<android/log.h>
//就可以使用_android_log_print方法打印日志到logcat中
ldLibs "log"
//编译生成支持对应cpu类型的so库
abiFilters "armeabi-v7a", "x86"
}
}
二、实现JNI
配置好NDK环境后,下面开始编写c/c++代码。
1、先定义Java 调用的native方法
public class NativeJNIMethod {
public static native String getNativieString();
public static native int add(int a, int b);
}
2、通过javac和javah命令生成对应.h文件
MApplication\app\src\main\java\com\example\mapplication\jniutil>javac NativeJNIMethod.java
MApplication\app\src\main\java>javah -jni com.example.mapplication.jniutil.NativeJNIMethod
命令执行后会生成一个class文件和.h文件分别生成在上面执行命令的对应目录下面。
3、在java目录下面新建jni目录
新建jni后将上面的.h文件拷贝到该目录下面,然后在jni目录下新建c或c++文件实现.h头文件中的方法。这里的.h文件相当于一种定义方法的接口。
新建c/c++文件实现.h中定义的方法
c++文件内容:
#include<com_example_mapplication_jniutil_NativeJNIMethod.h>
/*
* Class: com_example_mapplication_jniutil_NativeJNIMethod
* Method: getNativieString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_mapplication_jniutil_NativeJNIMethod_getNativieString
(JNIEnv *env, jclass type){
return env->NewStringUTF("HelloWorld来自jni的字符串");
}
/*
* Class: com_example_mapplication_jniutil_NativeJNIMethod
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_mapplication_jniutil_NativeJNIMethod_add
(JNIEnv *, jclass type, jint a, jint b){
return a+b;
}
四、调用native方法
在定义并实现好native方法后,下面的任务是编译成so库,然后就可以调用native方法了。
1、编译生成so库文件
在第一部分中配置ndk标签,标签中指定了生成so库的名称以及支持的cpu型号。然后直接点击Build---->Rebuild Project即可生成对应的so文件libHelloJni.so(so库文件名称是lib加上你在ndk节点中定义的moduleName名称)。编译后so库文件路径如下,然后将armeabi-v7a和x86两个文件夹拷贝到libs文件夹中。
2、加载so库
Android提供了4个实用的函数用来加载JNI库,分别是System.loadLibrary(libname),System.load(libFilePath),Runtime.getRuntime().loadLibrary(libname)和Runtime.getRuntime().load(libFilePath)。
通过查看代码发现System.loadLibrary(libname)和System.load(libFilePath)最终调用的方法分别和Runtime.getRuntime().loadLibrary(libname),Runtime.getRuntime().load(libFilePath)调用的方法是一致的。所以这四种方法其实就是两种方式。
虽然生成的so库文件名称是libHelloJni.so,当这个System.loadLibrary方法中写的库文件名称是你在ndk中moduleName 定义的名字"HelloJni"。
public class NativeJNIMethod {
static {
System.loadLibrary("HelloJni");
}
public static native String getNativieString();
public static native int add(int a, int b);
}
3、以上工作完成后,就可以在java代码中调用native方法了
((TextView) findViewById(R.id.jni_tv)).setText(NativeJNIMethod.getNativieString());
findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int add = NativeJNIMethod.add(10, 15);
((TextView) findViewById(R.id.sum)).setText(Integer.toString(add));
}
});
以上是实现简单JNI的操作步骤~,希望有所帮助。