NDK安装


ndk的安装是很直接的



  1. 访问 http://developer.android.com/tools/sdk/ndk/index.html ,从Downloads列表中选择适合你平台的NDK包
  2. 解压下载的NDK包
  3. 解压完成后,NDK文件放在一个叫做android-ndk-<version>的目录中。你可以改变它的名称,也可以把它移动到任何地方。
  4. 设置环境变量NDK指向ndk目录。   
    打开~/.bashrc文件,添加NDK=/home/robin/Desktop/android-ndk-r9c。
     source ~/.bashrc更新环境变量
  5. 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开发本地代码的大致流程:



  1. 把本地代码放在$PROJECT/jni/目录下
  2. 创建$PROJECT/jni/Android.mk,以向NDK构建系统描述你的项目,这是必须的
  3. 需要是创建$PROJECT/jni/Android.mk,以更详细的向构建系统描述你的项目。虽然这一步Android.mk不是必须的,但它允许你构建多CPU应用,或者重设某些编译/链接标志。
  4. 在你的工程目录,或者它的任何子目录,运行$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