Android NDK 预览



介绍:
Android NDK 是一个工具集,允许 Android 应用开发者将 C/C++ 源码编译后的本地机器源码嵌入到他们的应用程序包中。

重要:
  Android NDK 只能用在运行 Cupcake(Android-1.5) 或更高版本平台的目标 Android 系统镜像上。

  由于 1.5 版本发布之后改变了一些敏感的应用二进制借口(ABI)和工具链(toolchain),1.0 和 1.1 系统镜像就不再支持了

I. Android NDK 目标:
--------------------------------

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

  - 你的应用程序代码用"native" 关键字声名一个或多个方法,以表示它们是通过本地码实现的。例如:

    native byte[] loadFile(String filePath);

  - 你必须提供包含这些方法的本地共享库,这些库将打包进你的应用的.apk中。这些库必须根据标准的
    Unix 风格来命名,例如lib<something>.so,同时应该包含标准的 JNI 入口。例如:

    libFileLoader.so

  - 你的应用必须显式地加载库。例如为了在应用启动时加载,添加下面的语句到源码中即可:

    static {
      System.loadLibrary("FileLoader");
    }

  注意:在这里你不能使用 'lib' 前缀和 '.so' 后缀

Android NDK 是 Android SDK 的一个补充,它将帮助你:

  - 产生兼容JNI的可以运行在 Android 1.5 平台(或更高版本)的共享库

  - 拷贝产生的共享库到你的应用项目的恰当路径,这样它们会被自动地添加到你的最终以签名的.apk文件中
 
  - 在 NDK 的后续版本中,我们打算通过一个远程 gdb 连接提供帮助你调试你的本地代码的工具,并提供尽可能多的 source/symbol 信息

此外,Android NDK 提供:

  - 交叉工具链集(编译器,链接器等):可以在 Linux,OS X 和 Windows(通过Cygwin) 生成本地 ARM 二进制文件

  - 一系列 Android 平台支持的本地 APIs 对应的系统头文件。这些也保证在所有后续平台中得到支持
 
 它们被存档到文件 docs/STABLE-APIS.html

    重要:
    记住,Android 系统镜像中的大部分本地系统库不是一成不变的,也许在后续的平台升级中会有非常大的变化甚至被删除,

  - 一个 build 系统,允许开发者只需要写非常短的 build 文件来描述哪些代码需要编译以及如何编译。build 系统会处理所有杂乱的工具链/平台/CPU/应用二进制接口(ABI)的细节。此外,NDK的后续升级在为更多的工具链,平台,系统接口提供支持的同时,也不需要修改开发者的 build 文件。

II. 非 Android NDK 的目标
--------------------------------
对于编写在 Android 设备上运行的通用本地代码而言,NDK 并不是一个好方式。你的 app 应该仍然使用 Java 编程语言来书写,用 Java 来恰当地处理 Android 系统事件以避免应用无响应(ANR)事件以及用 java 来处理 app 的生命周期。

注意,尽管如此,在本地码中,通过应用包装器(Application wrapper)来恰当地启动/停止应用程序,也可以编写出复杂的应用程序

深入理解 JNI 是有必要的,因为在这个环节下的很多操作都需要开发者的细节动作。在典型的本地码中,虽然不普遍但是有必要提一提的是:

  - 不能够直接通过本地指针访问虚拟机对象的内容。例如:你不能很安全地获得一个指向 String 对象的 16 位字符数组的指针,并且在一个循环中迭代
 
  - 当本地码想要在虚拟机对象和 JNI 调用中保持句柄时,要求显式的引用  管理


NDK 只为 Android 平台支持的,非常有限的本地 APIs 和库提供系统头文件。当一个典型的 Android 系统镜像包含很多本地共享库时,必须考虑到在平台的升级和发布后可能发生重大改变的实现细节

如果一个 Android 系统库不为 NDK 显式地支持,那么在其上开发的应用程序不能在基于其可用的情况下开发,或者冒险下一次在众多设备商升级后打破该规则。


选择的系统库将逐步地被添加到稳定的NDK APIs 集合中

III. NDK 开发实践:
---------------------------
这里有一个使用 Android NDK 开发本地代码的概览:

  1/ 将你的本地码放在 $PROJECT/jni/... 下
 
  2/ 写一个 $PROJECT/jni/Android.mk 文件为 NDK build 系统描述你的源码

  3/ 可选项:写一个 $PROJECT/jni/Application.mk 文件,为 build 系统在更细节上描述你的项目。虽然你并不一定需要这个才能启动程序,但是这个允许你适合更多的 CPU 或者覆盖 编译器/链接器 标识 (获得更多细节,可以查看 docs/APPLICATION-MK.html)

  4/ 在项目目录下或者子目录下,运行 "$NDK/ndk-build" 创建你的本地码

如果成功的话,最后一步将拷贝空的共享库,你的 app 需要 app 项目的根目录。而你将需要用通常的方法产生最后的 .apk

现在,更多细节:

III.1 / 配置 NDK:
------------------------

之前的版本要求你运行 'build/host-setup.sh' 脚本来配置你的 NDK。而这一步在 NDK r4 中已经被完全移除了

III.2 / 存放 C 和 C++ 源文件:
-----------------------------

将你的本地码放在 $PROJECT/jni 中,$PROJECT 对应你的 Android app 项目的路径

你可以相当自由地按照你的想法组织 jni 的内容,这里的目录名和结构不包括最终生成的 app 包,所以你不需要非得用唯一包名,像 com.<mycompany>.<myproject>

注意,NDK 默认支持的 C++ 文件扩展名是 '.cpp',不过其他的扩展名也可以处理。(获取更多细节,可以查看 docs/ANDROID-MK.html)

你可以通过调整你的 Android.mk 文件来将你的源文件放在不同的目录下,如下:

III.3 /写一个 Android.mk 创建脚本:
--------------------------------------

一个 Android.mk 文件是一个很小的创建脚本,用来在 NDK build 系统中描述你的源码。他的语法在文件 docs/ANDROID-MK.html 中有详细描述

概括地说,NDK 会将你的源码组合成为一个模块,它们会是下面的其中一个:

  - 一个静态库
  - 一个共享库

你可以在一个 Android.mk 文件中定义若干个模块,或者写若干个 Android.mk 文件,每个定义一个单一的模块

注意,一个 Android.mk 会被 build 系统解析多次,所以不要假定其中某些变量无定义。默认情况下,NDK 将查找 build 脚本:
 
  $PROJECT/jni/Android.mk

如果你想在子目录下定义 Android.mk 文件,你应该在最高级 Android.mk 文件中显式地包含。存在有一个辅助函数干这个事儿,例如,使用:

  include $(call all-subdir-makefiles)

这个语句会将在当前 build 文件路径下所有子目录中的 Android.mk 文件包含进去

III.4 / 下一个 Application.mk build 文件 (可选)

----------------------------------------------------

写一个 Android.mk 文件向 build 系统描述你的模块,而 Application.mk 文件描述你的 app 本身。查看 docs/APPLICATION-MK.html 文档理解这个文件允许你做些什么。这包括,但不限于:

  - 你的 app 正好需要的模块
 
  - 产生机器码的 CPU 架构

  - 可选的信息,例如你是否想要发布或者调试 build 文件,特定的 C 或 C++ 编译器标识和其他用于创建所有模块的其他信息

这个文件是可选的,默认情况下,NDK 会在默认的目标 CPU ABI 下简单地提供一个编译在 Android.mk 文件中列出的(以及所有它包含的 makefiles 中列出的)所有模块的命令。

使用 Application.mk 有两种方式:

  - 放在 $PROJECT/jni/Application.mk 下,会被 'ndk-build' 脚本自动地捕获到

  - 放在 $NDK/apps/<name>/Application.mk 下,其中 $NDK 指向你的 NDK 安装路径。完了之后,在 NDK 目录下启动 'make APP=<name>'

  这是在 Android NDK r4 之前,Applicatin.mk 文件的使用方式。但是出于兼容性的目的,这是使用方式仍然支持,不过我们强烈鼓励你采用第一种方式,因为它更简单而且不需要修改/改变 NDK 安装树的目录


再次提醒,获取更多细节描述,查看 docs/APPLICATION-MK.html

III.5 /调用 NDK build 系统
-------------------------------

用 NDK 创建机器码的更好的方式是使用在 Android NDK r4 中介绍的 'ndk-build' 脚本。你也可以使用第二种,遗留下来的,依赖于创建 '$NDK/apps' 子目录的方法

在两种情况下,成功的创建最后会拷贝你的 app 需要的裁剪后的二进制模块(例如 共享库)到你的 app 项目路径下。(注意:为裁剪的版本出于调试的目的会留下来,没必要将为裁剪的二进制库拷贝到设备上)

  1:使用 'ndk-build' 命令:
  --------------------------

  位于 NDK 安装路径最顶部的 'ndk-build' 脚本可以从你的 app 项目目录(例如:你的 AndroidManifest.xml 存放的地方)下或者任何它的子目录下直接调用。例如:

  cd $PROJECT
  $NDK/ndk-build

  这将启动 NDK build 脚本,这个脚本会自动试探你的开发系统和 app 项目文件来确定创建什么

  例如:

  ndk-build
  ndk-build clean   --> 清理产生的二进制文件
  ndk-guild -B V=1  --> 强制重新创建,显示命令

  默认情况下,最后在 $PROJECT/jni/Application.mk 下存在可选的文件和在 $PROJECT/jni/Android.mk 目录下存在必须的文件

  成功之后,产生的二进制模块(例如:共享库)会被拷贝到你的项目树的合适位置下。接着你可以通过 ant 或者 ADT Eclipse plug-in 重建完整的 Android app 包

  获取更完整的关于这个脚本做些什么以及可以使用哪些可选项的信息,查看 docs/NDK-BUILD.html

  2:$NDK/apps/<name>/Application.mk
  -----------------------------------

  这个 build 方法是唯一在 Android NDK r4 之前支持,并且出于兼容的原因继续支持的方法。我们强烈地推荐你尽快适应使用 'ndk-build' 命令,因为我们也许会在后续 NDK 版本中移除这种支持

  它需要下面的一些东西:

    1. 在你的 NDK 安装目录(而不是你的项目路径下)下创建一个子目录,命名为:$NDK/apps/<name>/

    其中 <name> 是一个任意的名字,用来想 NDK build 系统描述你的 app

    2. 编写 $NDK/apps/<name>/Application.mk,这个需要一个定义 APP_PROJECT_PATH 指向你的 app 项目目录

    3. 用命令行进入 NDK 安装路径然后调用最高层的 GNUMakefile,如下:

      cd $NDK
      make APP=<name>

  除了这个方法产生的即时文件会被放在 $NDK/out/apps/<name/>下之外,结果和第一种方法基本相同

IV. 重建你的 app 包:

---------------------

用 NDK 产生二进制文件之后,你需要使用一般的方法重建你的 Android app 包文件(.apk),或者使用 ant 或者使用 ADT Eclipse plug-in

更多信息,可查看 Android SDK 文档。新的 .apk 会嵌入你的共享库,系统在安装 app 时会自动提取到它们。

V. 调试支持:

-------------

NDK 提供了一个辅助脚本,命名为 'ndk-gdb' ,易于启动你的 app 的一个本地调试会话。

本地调试只能在运行 Android 2.2 或者更高版本的设备上才能工作,只要你的app 是可调试的,则不需要根权限或者特权访问才能进行。

获取更多信息,查看 docs/NDK-GDB.html. 简而言之,本地调试遵循下列简单的原则:

  1. 确保你的 app 是可调试的(例如:在你的 AndroidManifest.xml 中设置 android:debuggable 为 "true")

  2. 用 'ndk-build' 创建你的 app,然后安装到你的设备/虚拟机上

  3. 运行你的 app

  4. 在你的 app 项目目录下运行 'ndk-gdb'

你会得到 gdb 提示。看 GDB 用户手册已更多获得有用指令。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值