当前android studio 版本3.0.1,步骤如下:
1.设置jni -h 和ndk -build的快捷方式
2.java代码写native方法以及设置动态链接库
3.快捷键jni -h生成头文件.h
4.建立c++资源文件和两个mk文件
5.快捷键ndk-build生成三种.so库文件
6.将生成的main/libs文件夹内的so文件复制到app/libs下,并删除main下新生成的jni、libs、obj三个文件夹(可选)。
7.在build.gradle中的android闭包和buildTypes闭包中分别添加sourceSets().
以上是步骤,具体如下:
1.置jni -h 和ndk -build的快捷方式:
新建项目,成功后点击File,然后找到Settings…点击找到External Tools,然后如下图添加java -jni快捷键
Tool settings中三行可以直接copy上去:
$JDKPath$\bin\javah.exe
-classpath . -jni -d $ModuleFileDir$/src/main/jni $FileClass$
$ModuleFileDir$\src\main\java
添加ndk-build快捷键如下图:
Tool settings 的两行:
F:\software\androidstudio\sdk\ndk-bundle\ndk-build.cmd(根据自己的ndk目录设置这个路径)
$ModuleFileDir$\src\main(直接copy)
使用方式:选中C/C++文件—>右键—>ExternalTools—>ndk-build,将在main文件夹下生成libs文件夹以及多个so文件,我们可以移动至jniLibs目录下去。
2.java代码写native方法以及设置动态链接库
public class JniTest {
/**
* 将用C++代码实现,在android代码中调用的方法:获取一段文字
*/
public static native String getStrFromC();
/**
* 配置加载的so库的文件名字===>如 :libmyLib.so
*/
static {
System.loadLibrary("myLib");
}
}
注意此处的myLib将与android.mk中的LOCAL_MODULE属性值一致;
3.快捷键jni -h生成头文件.h
然后对该文件执行javah -jni操作,生成对应的.h头文件。
如图,已经根据我们的java类在jni文件夹下生成了对应的.h文件,文件名为包名类名.h,我们可以手动改.h文件名,里面只有一个方法,返回值为String(jstring),方法名为Java类的包名类名方法名(包名中的分级不是用.而是_),前面两个参数是C++里面必须有的(JNIEnv代表指向JVM的指针,jclass是调用该方法的java对象),第三个jobject就是我们java类的方法里面的参数Object。注意,这是java函数与C++函数对应的静态注册方法,即通过特定的规则来写。此处方法名可以随意起名字,然后还可以用动态注册的方式关联两个方法。
4.建立c++资源文件和两个mk文件
在jni文件夹下,新建一个.c(c语言)或者.cpp(c++)的文件,来实现.h文件里声明的方法:
把.h文件里面声明的方法拷贝到新建的c文件里面,然后在文件里面引入.h文件,如下图:
至此,.h文件和c++文件已完成,想生成so文件还需要在这个jni目录下增加两个文件,Android.mk和Application.mk。
- Android.mk
注意LOCAL_MODULE的值与之前的java类中设置要生成so库的名字相对应,LOCAL_SRC_FILES的值写c++文件的名字,这两个值成对设置,可设置多组。(:=是赋值的意思,$是引用某变量的值。)
LOCAL_PATH := $(call my-dir) // 设置当前的编译目录(Android.mk所在的目录)
include $(CLEAR_VARS) // 清除LOCAL_XX变量(LOCAL_PATH除外)
LOCAL_MODULE := myLib // 指定当前编译模块的名称
LOCAL_SRC_FILES := jnittest.c // 编译模块需要的源文件
include $(BUILD_SHARED_LIBRARY) // 指定编译出的库类型,BUILD_SHARED_LIBRARY:动态库;BUILD_STATIC_LIBRARY:静态库, BUILD_EXECUTEABLE指:可执行文件
在一个Android.mk文件中配置多个Module的方式如下(include$(CLEAR_VARS)、include $(BUILD_SHARED_LIBRARY)两个语句也需要加上)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := myLib
LOCAL_SRC_FILES := jnittest.c
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := myLib2
LOCAL_SRC_FILES := jnittest2.c
include $(BUILD_SHARED_LIBRARY)
- Application.mk
APP_ABI := all
5.生成so文件
对C++文件执行ndk-build操作,生成相应的so文件
6.将生成的main/libs文件夹内的so文件复制到app/libs下,并删除main下新生成的jni、libs、obj三个文件夹(可选)。
7.在build.gradle中的android闭包和buildTypes闭包中分别添加sourceSets().
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.testopencv"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
sourceSets {
main {
//让AS识别libs下的.so第三方包
jniLibs.srcDirs =['libs']
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
sourceSets {
main {
jni.srcDirs = []
}
}
}
}