在上一篇博客Android 开发之JNI/NDK编程实战(一)中我们介绍了ndk环境的配置,以及如何在android studio3.0中实现jni编程,其原理其实是使用CMake+gradle的方式实现编译生成so库。接下来,我们探讨一下如何使用ndk+gradle的方式生成so库。
步骤:
- 1.ndk环境配置
- 2.新建项目,添加Jni实现类并生成.class文件
- 3.生成.h头文件
- 4.编写JniLib.cpp、Android.mk 、Application.mk文件
- 5.配置build.gradle脚本和ndk-build
- 6.编译生成so库
1.ndk环境配置
参考 Android 开发之JNI/NDK编程实战(一):android studio3.0配置ndk环境实现jni编程
2.新建项目,添加Jni实现类并生成.class文件
新建JniLib.java后,声明调用的so库名和本地方法
public class JniLib {
static {
System.loadLibrary("jnilib");
}
public native String getJniString();
}
然后拖拽JniLib所在路径到Terminal终端,执行
javac JniLib.java
生成class文件,如下图
3.生成.h头文件
拖拽java路径到Terminal终端,执行命令如下生成.h文件
javah -jni com.psp.jnitest2.JniLib
4.编写JniLib.cpp、Android.mk 、Application.mk文件
新建jni目录,将com_psp_jnitest2_JniLib.h 文件拷贝到jni目录下,新建JniLib.cpp文件,复制com_psp_jnitest2_JniLib.h里面的内容别修改如下
extern "C" {
#endif
/*
* Class: com_psp_jnitest2_JniLib
* Method: getJniString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_psp_jnitest2_JniLib_getJniString
(JNIEnv *env, jobject){
return (*env).NewStringUTF("this is my jni test2");
};
#ifdef __cplusplus
}
#endif
#endif
在jni目录下编写Android.mk
// 设置工作目录,而my-dir则会返回Android.mk文件所在的目录
LOCAL_PATH := $(call my-dir)
// 清除几乎所有以LOCAL——PATH开头的变量(不包括LOCAL_PATH)
include $(CLEAR_VARS)
// 设置模块的名称,即编译出来.so文件名
// 注,要和上述步骤中build.gradle中NDK节点设置的名字相同
LOCAL_MODULE := JniLib
// 指定参与模块编译的C/C++源文件名
LOCAL_SRC_FILES =: JniLib.cpp
// 指定生成的静态库或者共享库在运行时依赖的共享库模块列表。
include $(BUILD_SHARED_LIBRARY)
在jni目录下编写Application.mk
APP_MODULES :=JniLib
//指定需要基于哪些CPU平台的.so文件
//常见的平台有armeabi x86 mips,其中移动设备主要是armeabi平台
//默认情况下,Android平台会生成所有平台的.so文件,即同APP_ABI := armeabi x86 mips
//指定CPU平台类型后,就只会生成该平台的.so文件,即上述语句all会生成全部平台的.so文件
APP_ABI := all
5.配置build.gradle脚本和ndk-build
打开app下的build.gradle文件,在 defaultConfig 节点内添加ndk节点和sourceSets,如下
配置ndk-build,打开File-->Settings,配置ndk-build如下,配置好之后点击ok
6.编译生成so库
右键点击JNI类,即右键点击JniLib.java,调用ndk-build生成.so文件
结果如下:
至此,我们的so库就编译生成了。
注意:以上步骤中调用ndk-build如果出错,去掉Android,mk和Application.mk中的注释即可。