简介:
android NDK开发有通过外部的构建工具将原生代码构建成库文件,也有用开发工具自身带的,android studio支持CMake和ndk-build来构建原生库,这里我们介绍通过CMake来构建原生代码。
JNI和NDK
JNI全称是java native interface,即java原生代码接口,其作用就是连接底层代码c/c++和java之间的交互.
NDK全称是Native Development Kit,即原生开发的工具包,里面包含着快速开发的动态库,以及相关构建工具等
为什么使用JNI
- 支持跨平台,用c/c++编译的so库可以在其它平台上很好移植,复用度高
- 提高性能效率
- 代码安全性高,反编译难度大
下载安装工具
打开SDK Manager 安装android NDK,CMake,LLDB
- android NDK:原生开发工具包
- CMake :原生代码构建工具
- LLDB :调试原生代码程序工具
创建项目
在向导中勾选include c++ support,并设置下面选项
- C++ Standard:使用下拉列表选择您希望使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
- Exceptions Support:如果您希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
- Runtime Type Information Support:如果您希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
构建运行项目
- Gradle 调用您的外部构建脚本 CMakeLists.txt。
- CMake 按照构建脚本中的命令将 C++ 源文件 native-lib.cpp 编译到共享的对象库中,并命名为libnative-lib.so,Gradle 随后会将其打包到 APK 中。
- 运行时,应用的 MainActivity 会使用 System.loadLibrary() 加载原生库。现在,应用可以使用库的原生函数 stringFromJNI()。
- MainActivity.onCreate() 调用 stringFromJNI(),这将返回“Hello from C++”并使用这些文字更新 TextView。
CMakeLists.txt
CMakeLists.txt是构建脚本文件,这里我们看新创建的demo里的文件
这里我们通过相关cmake命令可知,这里是指定了cmake的版本,指定了库文件以及查找并关联了一个log的库文件
配置CMakeLists.txt文件路径
|
|
配置ABI
|
|
库命名
在cmake脚本文件里通过add_library命令中指定库文件名字,其产生文件格式为
lib库名称.so
代码中通过 System.loadLibrary(“库名称”);来进行库的加载
旧NDK版本支持
在gradle.properties中添加配置android.useDeprecatedNdk=true
ndk-build构建
除了cmake方式,我们还可以使用ndk-build方式构建,在编译文件目录下增加Android.mk文件和Application.mk文件
在Android.mk中配置编译相关配置
在Application.mk文件中则配置项目相关信息
在gradle中指定Android.mk构建文件的路径
最后通过cd命令到编译文件目录下通常为jni目录下执行ndk-build命令构建库文件即可打包成so包
开发流程
- 在Java中声明Native方法(即需要调用的本地方法)
- javac编译上述 Java源文件得到 .class文件
- 通过 javah 命令导出JNI的头文件(.h文件)
- 使用 Java需要交互的本地代码 实现在 Java中声明的Native方法
- 编译.so库文件
注册JNI函数
有两种方式可以注册JNI函数,一种是静态注册,一种是动态注册,静态注册就像上面讲的通过javah得到对应的头文件,实现其函数即可,动态注册则是通过库加载调用的JNI_OnLoad()函数中调用JNIEnv的RegisterNatives方法来完成注册native方法和JNI函数的对应关系
c调用java代码
通过FindClass()函数获取到对应的java类,然后通过GetMethodID()函数获取到对应的方法