最近越来越多物联网相关的应用,而对开发人员来说,JNI调用甚至NDK开发的频率也越来越高,所以在这里写一下学习心得,也希望对开始学习的人有所帮助。
准备工作:
1.Android Studio在2.3以上,有对C++代码的支持,所以我们配置好相关的内容会使日后理解C++代码或JNI里的方法有所帮助,首先,打开sdk manager,下载这两个工具,然后再new project时勾上对C++的支持
2.NDK的下载,可以自行下载,也可以直接Android Sudio里进行下载,点击File -> OtherSettings -> Default Project Structure..., 在NDK里download,完了后项目的local.properties会有ndk的配置信息
并在gradle.properties 加上 :
android.useDeprecatedNdk=true
下面开始进入主题,就由一个简单的由C++返回字符串的项目开始
新建一个ndklibrary的model作为library,然后创建一个java类,作为jni调用的native方法的声明,
public class StringJNI {
static {
System.loadLibrary("StringJNI");
}
public native String getHelloString();
}
类很简单,load了一个本地library,这里这个library就是我们要生成的,然后定义了一个native方法用来获取字符串,然后build.gradle配置编译信息
defaultConfig{
ndk{
moduleName "StringJNI" //so文件名,可以不与上面的类名一样
abiFilters 'armeabi-v7a', 'arm64-v8a' // 'x86', 'x86_64' 这里如果是写‘armeabi’,在新的NDK里
//是不支持导致编译不过
}
}
buildTypes{
sourceSets { main { jni.srcDirs = [] } }
}
然后能过javah命令开生成头文件,AS下打开terminal,输入以下命令
这时,如果提示javah不是内部命令,就先去配置环境变量,在有些类里,不加-encoding会报
编码GBK的不可映射字符。
然后就会在当前目录下生成一个头文件com_example_qjl_ndklibrary_StringJNI.h,这个文件的命名是固定的,包名加类名用_连接组成。然后new一个jni folder,把头文件放进去,并创建一个.cpp的C++类,引入头文件,由于前面加了C++的支持,这时我们打#in时,就会有代码补全的提示
有了这些提示,对我们写C++的代码也很有帮助,然后写完C++的方法
#include "com_example_qjl_ndklibrary_StringJni.h"
JNIEXPORT jstring JNICALL Java_com_example_qjl_ndklibrary_StringJni_getHelloString(JNIEnv *env, jobject jobject1) {
return (env) -> NewStringUTF("Hello JNI !");
}
这里先不考究代码的详细信息,只要知道返回了一个String,这个String是方法NewStringUTF转化的java的String。
这时代码的编写就完成了,然后编译代码,成功后会在build的ndk目录下有相应的so库
如果项目是依赖于整个ndklibrary工程的话,so库不用管,如果是生成jar包用的话,就要把so库放到当前的项目的libs文件夹下。
最后在要使用的地方
new StringJni().getHelloString()就可以了,由于后来类重命名过,所以有些是StringJni有些是StringJNI,这个大家不用理会,知道就好。
好了,整个JNI调用的步骤大概就这样子,希望对大家有所帮助,忘后再详细说说怎样配置,编译so库和一些jni里常用的函数等内容。