- 第一步 设置ndk路径 配置相应的开发环境
- 第二步 配置快捷键 Settings -> External tools中配置javah,javap,ndk-build快捷方式,(这一步主要是为了简化命令行输入,使用原生命令行也是可以的)
javah参数配置(直接拷贝):
Program: $JDKPath$\bin\javah.exe
Parameters: -classpath . -jni -o $ModuleFileDir$/src/main/jni/$Prompt$ $FileClass$
Working directory: $ModuleFileDir$\src\main\Java
Parameters的另外一种写法: -classpath . -jni -d $ModuleFileDir$/src/main/jni $FileClass$
javap参数配置(直接拷贝):*
Program: $JDKPath$\bin\javap
Parameters: -s -p $FileClass$
Working directory: $ModuleFileDir$\build\intermediates\classes\debug
ndk-build参数配置(直接拷贝):
Program: D:\Android_NDK\android-ndk-r11b\ndk-build.cmd
Working directory: $ModuleFileDir$\src\main
- 第三步 创建java类 引用即将创建的链接库,以及创建所需要的本地方法
1 | static { |
- 第四步 使用之前配置的javah快捷键快速生成.h头文件
此时 会自动创建jni目录并生成头文件
- 第五步 参考头文件 在jni目录下开始编写C/C++代码
注:
项目结构切换成 Android状态时,jni文件夹显示成 cpp名字!
当切换成project时就显示成jni文件夹!!
如下图:
添加如下代码:
- 第六步 配置gradle
1 | ndk{ |
点击Androidstudio 菜单栏 Build ->ReBuildProject 后自动生成Android.mk文件
把Android.mk文件拷贝到 main/jni文件夹下 然后右键—>External Tools –>ndk-build 生成 .so文件!!
其次 在项目的gradle.properties 文件中添加
1 | android.useDeprecatedNdk=true |
- 第七步 运行java代码 调取c库
注意事项
加载生成的动态库指定的文件名( System.loadLibrary(“MyJni”);)和生成.so时指定的名字(build.gradle中的ndk{moduleName “MyJni” }),还有Android.mk中LOCAL_MODULE := MyJni三者名称需要保持一致;
异常提示不支持c++
1
2
3
4
5
6
7
8
9
10Error: Flag android.useDeprecatedNdk is no longer supported and will be removed in the next version of Android Studio. Please switch to a supported build system.
Consider using CMake or ndk-build integration. For more information, go to:
https://d.android.com/r/studio-ui/add-native-code.html#ndkCompile
To get started, you can use the sample ndk-build script the Android
plugin generated for you at:
E:\IT\youban\module_c++\build\intermediates\ndk\release\Android.mk
Alternatively, you can use the experimental plugin:
https://developer.android.com/r/tools/experimental-plugin.html
To continue using the deprecated NDK compile for another 60 days, set
android.deprecatedNdkCompileLease=1570504380180 in gradle.properties解决方案:在build.gradle中添加如下配置即可:
1
2
3
4
5
6
7
8
9
10android{
//增加之后如下信息之后,右键项目的时候Link C++ Project with Gradle选项不再显示;
// externalNativeBuild {
// ndkBuild {
// path file('src/main/jni/Android.mk')
// }
// }
}
附:C调java代码
Java中代码如下:
1 | static { |
C中代码如下:
1 | //在c代码里面调用java代码里面的方法 |
注意事项:
- 原生方法在C和C++的调用方式不同,例如:
1 | /* C */ |
在C语言中,JNIEnv是指向JNINativeInterface结构的指针,使用它必须要解引用。而第一个参数还是env,学过C和C++语言都知道,C语言是面向过程语言,NewStringUTF只是一个函数指针,调用该方法还不清楚调用者,所以要传递env,而C++就不用,因为C++是面向对象语言,这个就不解释咯
2.关于C++调用C函数或者变量
1 | //在C++中引用C语言中的函数和变量,在包含C语言头文件时(假设为cExample.h),需进行以下处理: |
3.关于so文件的名称问题
Android.mk文件中的LOCAL_MODULE 决定了so文件的名称,LOCAL_MODULE 的名称可以手动修改也可以在build.gradle中配置:
1 | ndk { |
4.关于System.loadLibrary();
为什么loadLibrary中填入的名称不一致,却能依然运行成功不报错?
目前自测发现 build文件中出现很多编译后的so库 有可能是旧so库未及时清除的原因,可以过研究研究build文件夹,里面藏着非常多的秘密
5.ndk-build不执行照样运行成功
C/C++源码文件改动后自动调用ndk-build编译生成新的so库存放在build文件夹中,可以拷贝直接使用,ndk-build生成正式的so库,这跟apk打包是同样的道理 Android.mk文件是必须存在的,否则无法编译生成so库,也无法编译识别源文件
本文为作者原创 转载时请注明出处 谢谢
乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站