JNI简单入门

JNI(Java Native Interface),java本地开发接口,JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(C、C++),外部的C/C++代码也可以调用java代码。效率上,C/C++是本地语言,比java更高效,代码移植,复用现有C语言模块功能,提高代码的安全性,不易被反编译。

一、创建Java类,以实现JNI调用

这里我们新建一个JniUtils的Java类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* author:Toby
* e-mail:changhelaobiao@163.com
* time:2017/9/5
* desc: 测试类
*/

public class JniUtils {

// 加载C文件
static {
System.loadLibrary("JniUtils");
}

public static String keyCode = getKey();

// 定义一个方法,该方法在C或C++中实现
public static native String getKey();

}

二、执行Make Project生成class文件

执行Android Studio Build下的Make Project选项,生成生成JniUtils类的class文件:

三、利用class文件生成.h文件

打开Android Studio底部的控制台Terminal,切换到项目的app/src/main目录下,执行如下命令:

1
javah -d jni -classpath class文件的绝对路径

执行完成后可以在app/src/main目录下自动创建一个含有.h文件的jni文件夹:

四、编写C或C++源代码

将3步骤中生成的.h文件中的方法拷贝至新建的.c文件中,并实现其中的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//
// Created by Toby on 2017/9/5.
//

#include <com_lpx_jnidemo_JniUtils.h>

/*
* Class: com_lpx_jnidemo_JniUtils
* Method: getKey
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lpx_jnidemo_JniUtils_getKey
(JNIEnv *env, jobject obj){

return (*env)->NewStringUTF(env,"changhelaobiao");

}

五、配置app目录下的build.gradle文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.lpx.jnidemo"
minSdkVersion 14
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

ndk {
moduleName "JniUtils"
abiFilters 'armeabi', 'x86', 'armeabi-v7a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

注意:
a.其中,ndk是新添加进去的,同时配置了so库的类型。
b.还需要在生成的jni文件夹下创建一个空的util.c文件,否则会有异常(待测试)。

六、生成so库文件

运行app项目,即可在目录app\build\intermediates\ndk下面看到生成的so库文件。

七、so库文件的使用

在项目中新建jniLibs目录,并件so库拷贝至该目录中,然后即可在Android项目中使用so库中的方法了。



备注:
CPU架构的种类有:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64
参考资料:http://www.jianshu.com/p/3494741f0ad1

八、JNI与NDK的关系

JNI

定义:Java Native Interface,即Java本地接口
作用:使得Java能够与本地其他类型语言(如C/C++)进行交互

即在Java代码里调用C、C++等语言的代码或C、C++代码调用Java代码

注意:

1、JNI是 Java 调用 Native 语言的一种特性;

2、JNI 是属于 Java 的,与 Android 无直接关系

NDK

定义:Native Development Kit,是Android的一个工具包

NDK是属于Android的,与Java并无直接关系

作用:快速开发C、C++的动态库,并自动将so库和应用一起打包成apk文件,即通过NDK在Android中使用JNI与本地代码(C、C++)交互。

关系总结:JNI是实现的目的,NDK是在Android中实现JNI的手段,即在Android的开发环境(AS)中,通过NDK从而实现JNI的功能。

参考资料:
https://blog.csdn.net/carson_ho/article/details/73250163