Android NDK 概述


简介:
Android NDK 是一套工具,它允许 Android 应用程序开发人员嵌入本机代码,编译 C c + +源代码文件,放入其应用程序包。

注意:
Android NDK 只能在在安卓 或更高版本的平台面运行。1.0 1.1 系统映像有点特别,他不支持

subtle ABI1.5版本上的编译链变化。

一、 android NDK 目标:

——————————————————————————

Android 虚拟机允许应用程序源代码中要调用的方法在通过 JNI 本机代码中实现。简而言之,这意味着:

——您的应用程序的源代码将声明一个或多个方法通过实施以本机关键字,指示本机代码。

例如:native byte[] loadFile(String filePath);

——你必须提供一个本地共享库,包含了这些方法的实现,它将被打包到你应用程序中。这个库必须根据标准
  Unix约定 lib<something>.so。所以,应当包含一个标准的JNI入口点(稍后说明)。

例如:libFileLoader.so

——您的应用程序必须显式地加载库。例如,在应用程序启动的时候加载,只需添加以下其源代码:

  static {

System.loadLibrary("FileLoader");

}

  注意,不要lib和.so作为前缀和后缀。


Android NDK是Android SDK的一个补充,帮助您:

——生成jni兼容共享库,可以运行在ARM处理器Android1.5平台(更高)

——复制生成的共享库到你的工程项目适当的位置,那么他们将被自动添加到你的apk中。

随后的修正
——我们打算提供工具,通过一个远程gdb连接和尽可能多的源/符号信息,帮助调试本机代码。
此外,安卓NDK提供了:
——1组交叉工具链(编译器、连接器、等…),可以生成本地ARM二进制文件在Linux,OSX和Windows(用Cygwin)上运行。
——1套系统头文件对应于本地代码api接口,用于Android平台的支持。保证在以后的版本中支持所有的平台。
  他们都被记录在 docs/STABLE-APIS.html
注意:
  记住,在以后的更新和发布的平台,大多数的本地系统库在Android系统被冻结或者可能发生了彻底的变化,甚至删除。
——构建系统,它允许开发者只写很短的构建文件描述哪些资源需要被编译,以及如何编译。构建系统
  处理所有的工具链/平台/ CPU / ABI的细节。此外,后来更新的NDK可以支持更多的工具链、平台,
  系统接口,不需要改变在开发者的构建文件(稍后再说)。
二、Android NDK 非目标:
  ——————————————————————————

  NDK 不是一个好的方式来编写通用的本地代码,运行在Android设备。特别是,你的应用程序仍应写在Java编程语言,Android系统事件处理要适当避免“应用程序没有响应”对话框或处理Android应用程序生命周期。
请注意,还是可以写复杂的应用程序,适当地用"应用程序封装器"用来启动/停止它的本机代码。
强烈理解好JNI,因为许多操作在这种环境下需要特定的开发人员,这是不一定是常见的本机代码。这些包括:
-不能够通过本机的直接指针直接访问VM 对象的内容。例如您不能安全地获取一个指针,在一个循环中循环访问指向字符串对象中16位char数组的指针。
-需要显式引用管理,当本机代码想要对 VM 对象 JNI 调用之间保持的句柄。
NDK 只提供一组非常有限的本机系统标头Api 和 Android 平台所支持的库。尽管一个典型Android 系统包括许多本机共享的库,这些可能会大幅改变在更新和升级平台的版本。
如果 NDK 不显式支持 Android 系统库或者头文件,应用程序不应依赖它,它们可能会在其他系统或者硬件上发生异常。
选好的系统库逐渐的被添加到稳定 NDK Api集。
三。NDK 在实践中的发展:
---------------------------------
这里是非常粗糙的概述,您可以如何开发本机代码Android NDK:
1 / 放置你的本地代码到 $PROJECT/jni/...
2 / 写 $PROJECT/jni/Android.mk 来描述如何编译你的源码
3 / 可选: 写 $PROJECT/jni/Application.mk 来形容你的项目生成库的更多的详细信息。你不需要
一开始就写,但这使您可以为多个 CPU目标平台重写编译器/链接器标志。
(请参阅docs/APPLICATION-MK.html的所有详细信息)。
4 / 生成库 通过运行"$ NDK/ndk-build"从你项目目录中,或任何其子目录。
最后一步将复制,如果成功,共享库会复制到您的应用程序根项目目录。然后通过平时的方法生成最后的apk文件。
现在有几个配置 NDK 的详细信息:
III.1/:
- - - - - - - - - - - - - -
以前的版本要求您运行生成'build/host-setup.sh',要配置您的 NDK 脚本。这一步完全删除在release 4 (即 NDK r4).
III.2/ 放置 C 和 c + + 的来源:
- - - - - - - - - - - - - - - - -
将放在以下目录:
$PROJECT/jni/
$PROJECT 是项目相对应的 Android 应用程序的路径。
您可以很自由地组织 'jni' 的内容,你想,目录名称和结构在这里将不会影响最后生成应用程序的软件包,因此您不必使用 com.<mycompany>.<myproject>作为应用程序软件包的名称。
请注意 C 和 c + + 的源程序都支持。 NDK默认的 c + + 文件扩展名支持的是 '.cpp',但也可以处理其他扩展
(请参阅文档 docs/ANDROID-MK.html 代码的详细信息)。
有可能在不同的位置存储你的源码,通过调整您的智能手机.mk 文件 (见下文)。
III.3/ 编写 Android。mk 生成脚本:
- - - - - - - - - - - - - - - - - - - - - -
Android.mk 文件是一个小生成脚本,您写来形容你源码如何用NDK构建系统。它的语法详细描述是在
docs/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。
II.4/ 编写Application.mk 生成文件 (可选):
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Application.mk 文件描述了您对生成系统的模块。要了解此文件 请参阅 docs/APPLICATION-MK.html。
这包括,除这些外:
-您的应用程序所需的模块确切列表。

-要生成的机器代码 CPU architecture(s)。

-可选信息,如您希望发布版本或调试建造、特定的 C 或 c + + 编译器标志及其他,适用于所有正在修建的模块。
此文件是可选的: 在默认情况下 NDK 将提供一个,只是生成所有模块列出从您的Android.mk(和所有的它包括的makefiles) 和平台的默认 CPU ABI (armeabi)。
这里有两个方法可以使用Application.mk:

-根据 $PROJECT/jni/Application.mk,它将会被 'ndk-build'脚本自动选取 (更多在后面介绍)
-根据 $NDK/apps/<name>/Application.mk,其中 $NDK指向您 NDK 的安装路径。在此之后,从 NDK 目录启动
"make APP=<name>"。这是 Android NDK r4 之前,使用此文件的方式。
这是它还支持、兼容的原因,但我们强烈鼓励您改为使用第一种方法,因为它更简单,不需要修改 / 更改NDK 安装目录树。
再次请参考 docs/APPLICATION-MK。

III.5/ 调用 NDK 构建系统:
- - - - - - - - - - - - - - - - - -

建立与 NDK 的机器代码的首选的方式是使用'ndk-build'脚本,在Android NDK r4 ndk中介绍了。您还可以使用第二种,创建一个 '$NDK/apps' 子目录的方法。
在这两种情况下,生成成功,将复制最终的二进制模块(即从您的应用程序到您的应用程序所需的共享的库)
(请注意,原始的版本用于调试,没有必要将原始的二进制文件复制到设备)。
1: 使用"ndk-build"命令:
 ---------------------------------
"ndk-build"这个脚本位于ndk安装目录,你可以在应用程序目录(例如放AndroidManifest.xml的那个目录)或者其他子目录,例如:
cd $PROJECT $NDK/ndk-build
这将启动 NDK 生成脚本,它将自动探测您开发系统和应用程序项目文件,以确定能造出什么。
例如:
ndk-build 
ndk-build clean --> 清理生成的二进制文件
ndk-build -B V=1 --> 强制重新编译和显示编译细节
默认情况下,需要$PROJECT/jni/Application.mk和$PROJECT/jni/Android.mk。 
一旦成功了,就会复制二进制文件到你的工程目录树下,你可以重新编译应用程序包用"ant"命令或者ADT插件。 
详细的请看docs/NDK-BUILD.html。 

III.6/ 指定的自定义输出目录:
- - - - - - - - - - - - - - - - - - - - - - -

默认情况下,ndk-build 放置生成的所有中间文件到$PROJECT/obj目录,但是可以通过环境变量定义 NDK_OUT 选择一个不同的位置来指向一个不同的目录。
定义时,此变量将产生两个效果:
1 /,用$NDK_OUT替代后确保正常, $PROJECT/obj的所有文件都保存好.
2 / 它告诉 ndk-gdb 寻找$NDK_OUT,而不是 $PROJECT/obj 版本的生成的二进制文件。

四、重建您的应用程序包:
- - - - - - - - - - - - - - - - - - -

用NDK生成的二进制文件之后, 您需要重新生成您Android 应用程序包文件 (.apk),即
使用"ant"命令或 ADT Eclipse 的插件。

请参阅更多详细信息的 Android SDK 文档。在系统上安装apk时,新的 apk 会自动提取和嵌入您的共享的库到目标设备。

五、 调试支持:
- - - - - - - - - - -

NDK 提供了帮助器脚本,名为 ndk-gdb,这很容易启动您的应用程序的本机调试会话。

本机调试仅可以运行在设备Android 2.2 或更高上,并且不需要 root 或特权的访问权限,很长时间,您的应用程序是可调试的。

更多的信息,请参看 docs/NDK-GDB。html 。总括而言,本机调试有下面这个简单的几步:
1.确保您的应用程序是可调试 (例如设置您的 AndroidManifest.xml 中的android:debuggable ="true"。) 

2.用ndk-build构建您的应用程序,然后将其安装在您设备/模拟器。

3.启动您的应用程序。

4.从您的应用程序项目目录运行 ndk-gdb。

您将得到一个 gdb 提示符。请参阅 GDB 用户手册上有用的命令。