NDK是Android SDK自带的工具开发包,用于快速的开发C和C++的动态代码库,并将相关的so文件打包进APK文件中。JNI是Java语言增强的特性之一,用于Java与本地语言的交互。总结下来:JNI是实现的终极目标,而NDK是Android集成开发环境实现JNI目标的手段。 通过NDK实现JNI目标。
需要注意: NDK提供的库本身也是有限的,仅仅用于处理算法效率和敏感的问题,NDK提供了交叉编译器,用于生成特定的CPU的平台动态库,另外NDK还提供了.so文件和.apk打包的工具。
还记的AndroidStudio2.2的版本吗?还记得Eclipse开发NDK吗?简直苦不堪言啊。考虑到目前大部分同学已经迁移到AndroidStudio,况且我相信绝大同学的版本已经在3.2了吧。我们直接就讲解最新的AndroidStudio集成NDK开发的方式。
一个支持了NDK的Android的项目有哪些需要注意的点呢?
如果要手动将 Gradle 与你的本地库相关联,你需要在 module 层级的 build.gradle 文件中添加 externalNativeBuild {}
代码块,并且在该代码块中配置 cmake {}
或 ndkBuild {}
。可以看到AndroidStudio默认使用Cmake构建系统。后续我们着重来说。
cmake { cppFlags "-frtti -fexceptions" //这里的设置了一些可选的标识符给C++的编译器,这也是我们之前在创建项目时候勾选的 } 复制代码
add_library()
、 find_library
和 target_link_libraries
都是Cmake脚本中定义的命令函数。其他一些Cmake脚本语法可以参见https://cmake.org/cmake/help/v3.0/command/find_library.html(注意版本区分)。
add_library
使用指定的源文件向工程中添加一个库。函数原型如下:
add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN) # STATIC:静态库,是目标文件的归档文件,在链接其它目标的时候使用 # SHARED:动态库,会被动态链接,在运行时被加载 # MODULE:模块库,是不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数 复制代码
find_library
用于查找一个库文件。函数原型如下:
find_library( <VAR> name | NAMES name1 [name2 ...] [HINTS path1 [path2 ... ENV var]] [PATHS path1 [path2 ... ENV var]] [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC "cache documentation string"] [NO_DEFAULT_PATH] [NO_CMAKE_ENVIRONMENT_PATH] [NO_CMAKE_PATH] [NO_SYSTEM_ENVIRONMENT_PATH] [NO_CMAKE_SYSTEM_PATH] [CMAKE_FIND_ROOT_PATH_BOTH | ONLY_CMAKE_FIND_ROOT_PATH | NO_CMAKE_FIND_ROOT_PATH] ) # android系统每个类型的库会存放一个特定的位置,而log库存放在log-lib中 复制代码
target_link_libraries
设置要链接的库文件的名称。函数原型如下:
target_link_libraries(<target> [item1 [item2 [...]]] [[debug|optimized|general] <item>] ...) 复制代码
通过上面的解析,我们知道AndroidStudio默认使用Cmake进行NDK构建环境,通过在CMakeLists.txt中进行编辑命令的编写,使得C++/C的代码可以通过Cmake工具进行编译。
Java:函数的native申明是在MainActivity中。我们再看看MainActivity文件,与以前的jni调用方式完成一样,包括了库的加载、native方法申明、jni方法调用三个过程。在native方法中通过点击鼠标左键可以直接跳转到C++的源码里。
C++:这里是我们需要通过C/C++进行代码编写的地方。
我们在AndroidStudio中进行运行,把项目跑到手机中,当我们点击TextView,我们可以看到Hello from C++,说明我们成功进行了Java和C++代码的相互调用,也完成了JNI第一个入门程序的分析。