NDK安装
ndk的安装是很直接的
- 访问 http://developer.android.com/tools/sdk/ndk/index.html ,从Downloads列表中选择适合你平台的NDK包
- 解压下载的NDK包
- 解压完成后,NDK文件放在一个叫做android-ndk-<version>的目录中。你可以改变它的名称,也可以把它移动到任何地方。
- 设置环境变量NDK指向ndk目录。
打开~/.bashrc文件,添加NDK=/home/robin/Desktop/android-ndk-r9c。
source ~/.bashrc更新环境变量 - echo $NDK有内容输出,表示配置成功。或者执行$NDK/ndk-build,
Android NDK 简介
目标
Android NDK是一套工具,它允许Android应用开发者把C/C++编写的本地代码嵌入到Android应用包中。
Android VM允许你在你的Android应用源码中通过JNI调用本地代码编写的方法。
这意味着:
- 你的程序源码将会使用"native"关键字声明一到多个方法,以指明它们是通过本地代码实现的。 例如:native byte [] loadFile(String filePath)
- 你还必须提供一个包含这些方法的实现的本地共享库,共享库会被打包进你的应用.apk中。共享库的命名要符合标准的Unix规范(lib*.so,前缀是lib, 后缀是.so),还要包含标准的JNI入口点。
- 你的应用必须显示的加载用到的共享库。例如,简单的通过如下代码实现应用启动时加载:
static {
System.loadLibrary("FileLoader");
}
Android NDK是Android SDK的一部分,它的作用是:
- 生成兼容JNI的共享库,生成的共享库能够运行在使用ARM系列CPU的Android 1.5+平台上。
- Copy生成的共享库到你的应用项目路径下的合适位置,以便它们能够被自动添加到你最终的应用包.apks中
- 在将来的版本中,计划通过远程gdb连接来提供帮助调试本地代码的工具
更多的功能包括:
- 一套交叉工具链,帮助在Linux, OS X和windows上产生本地ARM二进制代码
- 一系列系统头文件,这些头文件中包含了Android平台支持的稳定的本地APIs列表。
- 一套构建系统,允许开发者只需要写很短的构建文件(build files)来描述哪些源文件需要编译,怎样编译。由构建系统系统处理所有繁杂的工具链/平台/CPU/ABI规范。此外,以后的版本将支持更多的工具链,平台和系统接口,而且不用改变构建文件。
非目标
用NDK并不是用来写Android通用本地代码的好方法。特别是应用程序,你应该用Java来写,处理好Android 系统事件,以避免弹出“应用未响应"对话框,还要处理好Android应用生命周期。
NDK开发实践
下面是使用Android NDK开发本地代码的大致流程:
- 把本地代码放在$PROJECT/jni/目录下
- 创建$PROJECT/jni/Android.mk,以向NDK构建系统描述你的项目,这是必须的
- 需要是创建$PROJECT/jni/Android.mk,以更详细的向构建系统描述你的项目。虽然这一步Android.mk不是必须的,但它允许你构建多CPU应用,或者重设某些编译/链接标志。
- 在你的工程目录,或者它的任何子目录,运行$NDK/ndk-build编译本地代码
最后一步,如果成功,将会把你应用程序需要的,编译好的动态库复制到你的应用的根项目目录。之后你需要通过通常的方法来生成最终的.apk。
更多的信息可以阅读ndk/docs下面的文档获取。
Android.mk构建脚本
Android.mk文件是一个小的构建脚本,用于向NDK构建系统描述你的源码信息。详细的语法可以查阅ANDROID-MK.html文档。
简言之,NDK把你的源代码组织成模块,每个模块可以是一个静态库,也可以是一个动态库。你可以在一个Android.mk中定义多个模块,你也可以写多个Android.mk文件,每一个定义一个单独的模块。
要注意,一个Android.mk文件可能被构建系统分析多次,所以不要假定其中的某个变量没有定义。默认情况下,NDK查找$PROJECT/jni/Android.mk这个构建脚本。
如果你想在子目录中定义Android.mk文件,你应该在顶层Android.mk中显示包含它们。有一个辅助功能来完成这件事,例如,使用:
include $(call all-subdir-makefiles)
这将会引入所有当前构建文件路径下的所有子目录中的Android.mk文件
NDK编译常见问题
NDK编译C++,提示找不到头文件
error: fstream: No such file or directory
error: set: No such file or directory
error: string: No such file or directory
解决办法:
在所在目录,新建文件Application.mk,添加 APP_STL := gnustl_static。
与STL相关的错误
1 异常相关的错误
error: exception handling disabled, use -fexceptions to enable。
2 某些STL函数找不到
undefined reference to `__cxa_end_cleanup'
undefined reference to `__cxa_begin_catch'
undefined reference to `__cxa_end_catch'
undefined reference to `__cxa_get_exception_ptr'
动态库编译正常include $(BUILD_SHARED_LIBRARY),改成静态库不编译include $(BUILD_STATIC_LIBRARY)
这是因为缺少Application.mk文件
解决方法:在<project>\jni\目录下添加一个Application.mk文件,里面写上一行代码:
APP_MODULES := libexample
注意:libexample的名字要与Android.mk中LOCAL_MODULE=example的名字相同
参考:官方文档 http://developer.android.com/tools/sdk/ndk/index.html#Installing