NDK开发入门(一)
1 简介
1.1 JNI与NDK的差异
- JNI(Java Native Interface)顾名思义为JAVA原生接口,定义了以JVM为基础的语言(Java &Kotlin)与本机代码(C / C ++)进行交互的方式。众所周知,Java具备跨平台的特性是因为带了虚拟机到处跑,而C与C++依赖于本机编译所用的ABI(Application Binary Interface,应用二元码接口,定义了机器语言的对齐方式、调用约定等)。所以C与C++书写的代码被称为本机代码或者原生代码。
- NDK(Native Development Kit)是谷歌提供的一套原生开发工具包。配置了这套工具包,Android Studio或者Eclipse就可以在Android 应用中使用C 和 C++ 代码进行开发。开发的APP既可以是纯原生的(为此谷歌提供了NativeActivity 来控制UI),也可以是Java与C++混合开发的。但是由于Java在控制UI方面有比较明显的优势,官方推荐混合开发。
1.2 NDK在Android开发中的用途
- 进一步提升设备性能,以实现低延迟时间,或运行计算密集型应用,如游戏、物理模拟和图形计算等。
- 重复使用您自己或其他开发者的 C 或 C++ 库。
2 安装配置环境
2.1 基本工具的下载
- 打开Android SDK(windows环境下 File->Settings 搜索 Android SDK,文章后续流程中将默认开发环境为Windows),选中右侧SDK Tools的栏目,如下图所示。
- 选中LLDB,CMake与NDK复选框,点击右下apply按钮进行工具下载。//此处可能需要科学上网
- LLDB:用来debug native代码的debug工具,如果不下载这个工具,Android Studio只能调试Java代码,后续调试的部分,会针对此工具的使用进行详细解释。
- CMake (Cross Platform Make):一个外部构建工具与Gradle协同工作构建本地的SO库,是目前官方推荐的集成工具。Cmake是一个跨平台的编译工具,可以保证不同的平台上,所书写的CMakeList文档具有一致性。
- NDK就是一个开发native代码的工具,包括一些基本的库和头文件等。
2.2 在Android Studio 中更换NDK版本
- 上述文档中,我们已经下载了NDK工具,默认情况下Android Studio会自动下载最新版本的NDK,并将其配置好。但凡事总有例外。
- 有时候安装目录过长Android Studio 会报错,或者开发需指定特定版本的NDK(例如opencv等库极可能不支持最高版本的NDK)。
- 下载所需版本的NDK->NDK历史版本下载。
- File->Project Structure,配置解压后的NDK路径 。
2.3 调试代码与debug
- 点击右上角的chose process按钮,可以进行debug模式的选择,如下图 所示。
- 在上述debugger的下拉选择框中,一共有四种模式,分别是Auto、Java、Dual、Native。其中Java模式下只会开启普通的debug窗口,Native下只会开启上文安装的LLDB,Dual模式下则会双开。虽然谷歌声称默认Auto是双开的,但在笔者的机器上和Java模式等同,而不是和Dual模式等同。
- 选择Dual模式,点击debug按钮,进入debug的界面看一下,这种模式之下就既可以debug Java又能debug C++了。
3 在Android 应用中添加C++代码
3.1 新建支持C++的Android 项目
- File->new->new Project,依次如下图直接next到最后finish即可。
3.2 在原有项目中添加C++支持
- 一般情况下,都是在原有项目中新增C++支持。
- 首先我们先看下同样是默认生成的项目的目录结构的对比,切到反映真实目录结构的Project视图。可以发现多了个一个CPP目录,而且里面有两种文件一种是CMakeList文件,一种是.cpp文件。所以在原有项目中应新增cpp目录。
- 右键main目录,新建一个directory,命名为cpp。
- 然后把另一个工程的文件复制过来就好了,由于MainActivity的代码也不一样,需要同样变更。(下篇讲工程的每个文件的作用以及浅显的原理)
- 点击运行,然后报错,找不到libnative-lib.so文件,事实上这个动态so库是cmake这个外部构建工具按照CMakeLists.txt定下的规则编译出的动态链接库。上文提到cmake是一种外部构建工具需要和gradle一起协同工作,现在会报错是因为CMakeLists.txt并没有和Gradle建立联系。在Android应用构建时并没有构建相应的so库,所以才会报错说找不到。
- 右键CMakeLists.txt->Link C++ Project with Gradle
- 实际上Link C++ Project with Gradle这一步操作IDE所做的工作,就是在app目录下的build.gradle文件中,添加了外部构建工具cmake的构建规则CMakeLists的目标指向。故而可以直接打开app目录下的build.gradle文件添加下述内容,与刚刚操作的结果一致。
- 此时在运行,还是有问题……找不到native具体的实现方法,是因为从另一个工程直接复制的原因,所以native代码具体实现的包名是有区别的。
- 所以在native-lib中改一下函数名即可找到native方法的具体实现。在ndk开发中,这种函数映射方案被称为静态注册,在后续的文章中,会详细解释。
- 成功运行。