英文文档见android-ndk-r5b的documentation.html
属于Android Native Development Kit (NDK)的一部分
见http://developer.android.com/sdk/ndk/(需要代理)
翻译仅个人见解
-----------------
Android NDK Overview
Android NDK概述
Introduction:
介绍
The Android NDK is a set of tools that allows Android application developers to embed native machine code compiled from C and/or C++ source files into their application packages.
Android NDK是一组工具,允许Android应用程序开发者把从C和/或C++源文件编译的原生机器代码嵌入到他们的应用程序包中。
IMPORTANT:
The Android NDK can only be used to target Android system images running Cupcake (a.k.a 1.5) or later versions of the platform.
重要:
Android NDK只能用于目标环境为运行Cupcake(即1.5)或更新版本的平台的Android系统镜像。
1.0 and 1.1 system images are specifically *not* supported due to subtle ABI and toolchain changes that happened for the 1.5 release.
特别地,1.0和1.1系统镜像不支持,因为1.5发布版发生一些微妙的ABI和工具链的改变。
I. Android NDK Goals:
一、Android NDK目标:
---------------------
The Android VM allows your application's source code to call methods implemented in native code through the JNI. In a nutshell, this means that:
Android虚拟机允许你的应用程序源代码通过JNI调用用原生代码实现的方法。概括来说,这意味着:
- Your application's source code will declare one or more methods with the 'native' keyword to indicate that they are implemented through native code. E.g.:
- 你的应用程序的源代码将用native关键词声明一个或更多个方法以指明它们通过原生代码实现。例如:
native byte[] loadFile(String filePath);
- You must provide a native shared library that contains the implementation of these methods, which will be packaged into your application's .apk. This library must be named according to standard Unix conventions as lib<something>.so, and shall contain a standard JNI entry point (more on this later). For example:
- 你必须提供一个原生动态库,包含这些方法的实现,它将被封装进你的应用程序.apk。这个库必须根据标准Unix约定命名为lib<名称>.so,并且包含一个标准JNI入口点(后面会详细说)。例如:
libFileLoader.so
- Your application must explicitly load the library. For example, to load it at application startup, simply add the following to its source code:
- 你的应用程序必须显式地加载库。例如,为了在应用程序启动时加载它,简单地添加以下内容到它的源代码中:
static {
System.loadLibrary("FileLoader");
}
Note that you should not use the 'lib' prefix and '.so' suffix here.
注意这里你不应该使用lib前缀和.so后缀
The Android NDK is a complement to the Android SDK that helps you to:
Android NDK是对Android SDK的补充,帮助你:
- Generate JNI-compatible shared libraries that can run on the Android 1.5 platform (and later) running on ARM CPUs.
- 生成JNI兼容的动态库,可以运行于Android 1.5平台(或更新),而这些平台则是运行于ARM CPU上。
- Copy the generated shared libraries to a proper location of your application project path, so they will be automatically added to your final (and signed) .apks
- 复制生成的动态库到你的应用程序项目路径的合适位置,然后它们将会被自动添加到你的最终的(和签名的).apk中。
- In later revisions of the NDK, we intend to provide tools that help debug your native code through a remote gdb connection and as much source/symbol information as possible.
- 较新修订版的NDK,我们倾向于提供工具帮助你通过一个远程gdb连接和尽可能多的源码/符号信息,调试你的原生代码。
Moreover, the Android NDK provides:
此外,Android NDK提供:
- A set of cross-toolchains (compilers, linkers, etc..) that can generate native ARM binaries on Linux, OS X and Windows (with Cygwin)
- 一套交叉工具链(编译器,链接器,等等)可以在Linux,OS X和Windows(带Cygwin)上生成原生ARM二进制文件。
- A set of system headers corresponding to the list of stable native APIs supported by the Android platform. This corresponds to definitions that are guaranteed to be supported in all later releases of the platform.
- 一套系统头文件对应Android平台支持的稳定原生API列表。它对应一些定义,它们保证在所有较新平台发布版中被支持。
They are documented in the file docs/STABLE-APIS.html
它们在文件docs/STABLE-APIS.html中有文档介绍。
IMPORTANT:
Keep in mind that most of the native system libraries in Android system images are not frozen and might changed drastically, or even deleted, in later updates and releases of the platform.
重要:
记住Android系统镜像中大多数原生系统库不是固定的,可能在平台后来的更新和发布中突然被改变,甚至会被删除,
- A build system that allow developers to only write very short build files to describe which sources need to be compiled, and how. The build system deals with all the hairy toolchain/platform/CPU/ABI specifics. Moreover, later updates of the NDK can add support for more toolchains, platforms, system interfaces without requiring changes in the developer's build files (more on this later).
- 一个构建系统,允许开发者仅书写非常短的构建文件以描述那些源文件需要被编译,以及如何被编译。构建系统处理所有杂乱的工具链/平台/CPU/ABI细节。然而,较新的NDK升级版可以添加对更多工具链、平台、系统接口的支持,而不需要修改开发者的构建文件(详细见下)
II. Android NDK Non-Goals:
二、Android NDK的非目标:
--------------------------
The NDK is *not* a good way to write generic native code that runs on Android devices. In particular, your applications should still be written in the Java programming language, handle Android system events appropriately to avoid the "Application Not Responding" dialog or deal with the Android application life-cycle.
NDK不是一个书写运行在Android系统上的通用原生代码的好方法。特别地,你的应用程序仍然应该用Java编程语言书写,正确地处理Android系统事件以避免“应用程序没响应”对话框或处理Android应用程序生命周期。
Note however that is is possible to write a sophisticated application in native code with a small "application wrapper" used to start/stop it appropriately.
然而注意,可以用原生代码书写一个复杂的应用程序,带有一个小型“应用程序封装者”用于正确地开始或停止它。
A good understanding of JNI is highly recommended, since many operations in this environment require specific actions from the developers, that are not necessarily common in typical native code. These include:
强烈建议对JNI有良好的理解,因为在这种环境中许多操作需要开发者作出特定的动作,这些动作在通常的原生代码中不一定常见。这些动作包括:
- Not being able to directly access the content of VM objects through direct native pointers. E.g. you cannot safely get a pointer to a String object's 16-bit char array to iterate over it in a loop.
- 不能通过原生指针直接访问VM对象的内容。例如,你不能安全地获得指向字符串对象16位字符数组的指针以在循环中迭代它。
- Requiring explicit reference management when the native code wants to keep handles to VM objects between JNI calls.
- 当原生代码需要在JNI调用之间保存VM对象的句柄,需要显式引用管理。
The NDK only provides system headers for a very limited set of native APIs and libraries supported by the Android platform. While a typical Android system image includes many native shared libraries, these should be considered an implementation detail that might change drastically between updates and releases of the platform.
NDK仅提供Android平台支持的非常有限集合的原生API和库的系统头文件。虽然一个典型的Android系统镜像包含许多原生动态库,但这些库应该被认为是实现细节,它们可能在平台的更新和发布之间突然被改变。
If an Android system library is not explicitly supported by the NDK headers, then applications should not depend on it being available, or they risk breaking after the next over-the-air system update on various devices.
如果一个Android系统库不能显式地被NDK头文件支持,那么应用程序不应该依赖于它是可用的,否则它们在不同设备的下一个无线系统更新之后会遭受破坏。
Selected system libraries will gradually be added to the set of stable NDK APIs.
所选择的系统库将逐渐添加到稳定NDK API集合中。
III. NDK development in practice:
三、实际的NDK开发:
---------------------------------
Here's a very rough overview of how you can develop native code with the Android NDK:
这里是一个非常粗略的概述,关于你可以如何用Android NDK开发原生代码:
1/ Place your native sources under $PROJECT/jni/...
1、放置你的原生源文件在$PROJECT/jni/...
2/ Write $PROJECT/jni/Android.mk to describe your sources to the NDK build system
2、书写$PROJECT/jni/Android.mk向NDK构建系统描述你的源文件。
3/ Optional: write $PROJECT/jni/Application.mk to describe your project in more details to the build system. You don't need one to get started though, but this allows you to target more than one CPU or override compiler/linker flags (see docs/APPLICATION-MK.html for all details).
3、可选:书写$PROJECT/jni/Application.mk更详细地向构建系统描述你的工程。虽然你入门时不需要它,但它允许你把目标定为多于一种CPU或重载编译器/链接器开关(所有细节请查看docs/APPLICATION-MK.html)。
4/ Build your native code by running "$NDK/ndk-build" from your project directory, or any of its sub-directories.
4、通过在你的工程目录中,或者它的任意子目录,运行$NDK/ndk-build构建你的原生代码。
The last step will copy, in case of success, the stripped shared libraries your application needs to your application's root project directory. You will then need to generate your final .apk through the usual means.
如果成功,最后的步骤将复制你的应用程序所需的被剪裁的动态库到你的应用程序的根工程目录。然后你将需要通过正常途径生成你的最终.apk。
Now, for a few more details:
现在,一些更详细的细节:
III.1/ Configuring the NDK:
三.1/ 配置NDK:
- - - - - - - - - - - - - -
Previous releases required that you run the 'build/host-setup.sh' script to configure your NDK. This step has been removed completely in release 4 (a.k.a. NDK r4).
以前的发布版需要你运行build/host-setup.sh脚本以配置你的NDK。这个步骤已经在发布版4(即NDK r4)中被完全移除。
III.2/ Placing C and C++ sources:
三.2/ 放置C和C++源文件:
- - - - - - - - - - - - - - - - -
Place your native sources under the following directory:
放置你的原生源文件在以下目录:
$PROJECT/jni/
Where $PROJECT corresponds to the path of your Android application project.
这里$PROJECT对应你的Android应用程序工程路径。
You are pretty free to organize the content of 'jni' as you want, the directory names and structure here will not influence the final generated application packages, so you don't have to use pseudo-unique names like com.<mycompany>.<myproject> as is the case for application package names.
你有很大的自由度根据你的意愿组织jni的内容,这里的目录名称和结构将不影响最终生成的应用程序包,所以你不必使用伪唯一的名称,即像应用程序包名com.<mycompany>.<myproject>那样的名称。
Note that C and C++ sources are supported. The default C++ file extensions supported by the NDK is '.cpp', but other extensions can be handled as well (see docs/ANDROID-MK.html for details).
注意,它支持C和C++源文件。NDK支持的默认C++文件扩展名为.cpp,但其它扩展名也可以处理(详细见docs/ANDROID-MK.html)
It is possible to store your sources in a different location by adjusting your Android.mk file (see below).
可以通过调整你的Android.mk,把你的源文件保存在不同位置(见下)。
III.3/ Writing an Android.mk build script:
三.3/ 书写一个Android.mk构建脚本:
- - - - - - - - - - - - - - - - - - - - - -
An Android.mk file is a small build script that you write to describe your sources to the NDK build system. Its syntax is described in details in the file docs/ANDROID-MK.html.
一个Android.mk文件是一个小型构建脚本,你书写它向NDK构建系统描述你的源文件。它的语法在文件docs/ANDROID-MK.html中详细描述。
In a nutshell, the NDK groups your sources into "modules", where each module can be one of the following:
概括来说,NDK把你的源码组织成“模块”,这里每个模块可能是以下的其中一种:
- a static library
- 一个静态库
- a shared library
- 一个动态库
You can define several modules in a single Android.mk, or you can write several Android.mk files, each one defining a single module.
你可以在单个Android.mk文件中定义多个模块,或者你可以书写多个Android.mk文件,每个文件定义一个单一模块。
Note that a single Android.mk might be parsed several times by the build system so don't assume that certain variables are not defined in them. By default, the NDK will look for the following build script:
注意一个单一Android.mk文件可能被构建系统多次解析,所以不要假设在它们里面某些变量没有被定义。默认,NDK将搜索以下构建脚本:
$PROJECT/jni/Android.mk
If you want to define Android.mk files in sub-directories, you should include them explicitly in your top-level Android.mk. There is even a helper function to do that, i.e. use:
如果你想在子目录中定义Android.mk文件,你应该显式地在你的顶级Android.mk文件中包含它们。甚至有一个辅助函数可以做到这点,即使用:
include $(call all-subdir-makefiles)
This will include all Android.mk files in sub-directories of the current build file's path.
它将包含当前构建文件路径下子目录中的所有Android.mk文件。
III.4/ Writing an Application.mk build file (optional):
三.4/ 书写一个Application.mk构建文件(可选):
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
While an Android.mk file describes your modules to the build system, the Application.mk file describes your application itself. See the docs/APPLICATION-MK.html document to understand what this file allows you to do. This includes, among others:
一个Android.mk文件向构建系统描述你的模块,而Application.mk文件、则描述你的应用程序自身。见docs/APPLICATION-MK.html文档以理解这个文件允许你做什么。它包含以下内容,以及其它:
- The exact list of modules required by your application.
- 你的应用程序所需的精确模块列表
- The CPU architecture(s) to generate machine code for.
- 生成机器代码所需的CPU架构。
- Optional information, like whether you want a release or debug build, specific C or C++ compiler flags and others that should apply to all modules being built.
- 可选信息,像你想要一个发布版构建还是一个调试版构建,应该被应用于所有被构建模块的特定C或C++编译器开关和其它参数。
This file is optional: by default the NDK will provide one that simply builds *all* the modules listed from your Android.mk (and all the makefiles it includes) and target the default CPU ABI (armeabi).
这个文件是可选的:默认NDK将提供一个配置文件简单地构建在你的Android.mk中列出的所有模块(以及所有它包含的makefile)以及目标定为默认的CPU ABI(armeabi)。
There are two ways to use an Application.mk:
有两种方法使用Application.mk:
- Place it under $PROJECT/jni/Application.mk, and it will be picked up automatically by the 'ndk-build' script (more on this later)
- 把它放在$PROJECT/jni/Application.mk,它将被ndk-build脚本自动地提取出来(详细见下)
- Place it under $NDK/apps/<name>/Application.mk, where $NDK points to your NDK installation path. After that, launch "make APP=<name>" from the NDK directory.
- 把它放在$NDK/apps/<name>/Application.mk,这里$NDK指向你的NDK安装路径。然后,从NDK目录中启动make APP=<name>。
This was the way this file was used before Android NDK r4. It is still supported for compatibility reasons, but we strongly encourage you to use the first method instead, since it is much simpler and doesn't need modifying / changing directories of the NDK installation tree.
这是在Android NDK r4之前使用此文件的方法。处于兼容原因它仍然被支持,但我们强烈鼓励你改为使用第一种方法,因为它更加简单而且不需要修改或更改NDK安装树的目录。
Again, see docs/APPLICATION-MK.html for a complete description of its content.
然后,它的内容的完整描述请参考docs/APPLICATION-MK.html。
III.5/ Invoke the NDK build system:
三.5/ 调用NDK构建系统:
- - - - - - - - - - - - - - - - - -
The preferred way to build machine code with the NDK is to use the 'ndk-build' script introduced with Android NDK r4. You can also use a second, legacy, method that depends on creating a '$NDK/apps' subdirectory.
用NDK构建机器代码最佳方法是使用由Android NDK r4引入的ndk-build脚本。你还可以用第二种遗留方法,依赖于创建一个$NDK/apps子目录。
In both cases, a successful build will copy the final stripped binary modules (i.e. shared libraries) required by your application to your application's project path (Note that unstripped versions are kept for debugging purposes, there is no need to copy unstripped binaries to a device).
在这两种情况下,一个成功的构建将复制你的应用程序所需的最终剪裁的二进制模块(即动态库)到你的应用程序工程路径(注意非剪裁版被保留作为调试用途,没必要复制非剪裁的二进制文件到设备中)。
1: Using the 'ndk-build' command:
1:使用ndk-build命令
---------------------------------
The 'ndk-build' script, located at the top of the NDK installation path can be invoked directly from your application project directory (i.e. the one where your AndroidManifest.xml is located) or any of its sub-directories. For example:
ndk-build脚本,位于NDK安装路径的顶级,可以在你的应用程序工程目录中直接调用(即你的AndroidManifest.xml所处的目录)或它的任意子目录。例如:
cd $PROJECT
$NDK/ndk-build
This will launch the NDK build scripts, which will automatically probe your development system and application project file to determine what to build.
这将启动NDK构建脚本,它将自动地探测你的开发系统和应用程序工程文件以决定构建什么东西。
For example:
例如:
ndk-build
ndk-build clean --> clean generated binaries
ndk-build clean --> 清除生成的二进制文件
ndk-build -B V=1 --> force complete rebuild, showing commands
ndk-build -B V=1 --> 强制完整的重构建,显示命令
By default, it expects an optional file under $PROJECT/jni/Application.mk, and a required $PROJECT/jni/Android.mk.
默认,它期待$PROJECT/jni/Application.mk这个可选文件,还需要$PROJECT/jni/Android.mk。
On success, this will copy the generated binary modules (i.e. shared libraries) to the appropriate location in your project tree. You can later rebuild the full Android application package either through the usual 'ant' command, or the ADT Eclipse plug-in.
成功的话,它将复制生成的二进制模块(即动态库)到你的工程树的合适位置。后面你可以通过惯常的ant命令或者ADT Eclipse插件,重新构建完全的Android应用程序包。
See docs/NDK-BUILD.html for a more complete description of what this script does and which options it can take.
关于这个脚本做什么以及它可以携带的选项的更完整描述请参考docs/NDK-BUILD.html
2: Using the $NDK/apps/<name>/Application.mk:
2:使用$NDK/apps/<name>/Application.mk
---------------------------------------------
This build method was the only one before Android NDK r4 and is only supported for compatibility reason. We strongly recommend you to migrate to using the 'ndk-build' command as soon as possible, since we may remove legacy support in a later NDK release.
这种构建方法是在Android NDK r4之前的唯一办法,只是出于兼容性原因而被支持。我们强烈建议你尽快迁移为使用ndk-build命令,因为我们可能在稍后的NDK发布版中移除这项遗留支持。
It requires the following:
它需要以下步骤:
1. Creating a sub-directory named $NDK/apps/<name>/ under your NDK installation directory (not your project path).
1. 在你的NDK安装目录中创建一个名为$NDK/apps/<name>/的子目录(而非你的工程路径)。
Where <name> is an arbitrary name to describe your application to the NDK build system (no spaces allowed).
这里<name>是一个任意名称,向NDK构建系统描述你的应用程序(不允许空白字符)。
2. Write $NDK/apps/<name>/Application.mk, which then requires a definition for APP_PROJECT_PATH that points to your application project directory.
2. 书写$NDK/apps/<name>/Application.mk,然后它需要一个APP_PROJECT_PATH定义,指向你的应用程序工程目录。
3. Go to the NDK installation path on the command line then invoke the top-level GNUMakefile, as in:
3. 在命令行中移动到NDK安装路径然后调用顶级的GNUMakefile,像这样子:
cd $NDK
make APP=<name>
The result will be equivalent to the first method, except for the fact that intermediate generated files will be placed under $NDK/out/apps/<name>/
结果将等效于第一种方法,不同的是事实上生成的文件将放在$NDK/out/apps/<name>/目录下
IV. Rebuild your application package:
四、重新构建你的应用程序包:
- - - - - - - - - - - - - - - - - - -
After generating the binaries with the NDK, you need to rebuild your Android application package files (.apk) using the normal means, i.e. either using the 'ant' command or the ADT Eclipse plug-in.
在使用NDK生成二进制文件后,你需要使用正常方式重新构建你的Android应用程序包文件(.apk),即使用ant命令或ADT Eclipse plug-in。
See the Android SDK documentation for more details. The new .apk will embed your shared libraries, and they will be extracted automatically at installation time by the system when you install the package on a target device.
更多细节请参考Android SDK文档。新的.apk将嵌入你的动态库,而它们将在安装期,你在目标设备上安装这个包时被系统自动抽取。
V. Debugging support:
五、调试支持:
- - - - - - - - - - -
The NDK provides a helper script, named 'ndk-gdb' to very easily launch a native debugging session of your applications.
NDK提供给一个辅助脚本,名为ndk-gdb,以非常容易地启动你的应用程序的一个原生调试会话。
Native debugging can *ONLY* be performed on production devices running Android 2.2 or higher, and does not require root or privileged access, as long as your application is debuggable.
原生调试只可以执行在运行Android 2.2或更高的产品设备上,不需要root或特权访问,只要你的应用程序是可调试的。
For more information, read docs/NDK-GDB.html. In a nutshell, native debugging follows this simple scheme:
更多信息,请阅读docs/NDK-GDB.html。概括来说,原生调试允许这个简单步骤:
1. Ensure your application is debuggable (e.g. set android:debuggable to "true" in your AndroidManifest.xml)
1. 确保你的应用程序时可调式的(例如,在你的AndroidManifest.xml文件中把android:debuggable属性设置为true)
2. Build your application with 'ndk-build', then install it on your device/emulator.
2. 用ndk-build构建你的应用程序,然后在你的设备或模拟器上安装它。
3. Launch your application.
3. 启动你的应用程序。
4. Run 'ndk-gdb' from your application project directory.
4. 从你的应用程序目录中运行ndk-gdb。
You will get a gdb prompt. See the GDB User Manual for a list of useful commands.