Android NDK概述

Android NDK概述

介绍:

Android NDK是一套工具,允许Android应用开发者嵌入从C、C++源代码文件编译来的本地机器代码到各自的应用软件包中。

重要:
    Android NDK 只能被用于使用该平台的Cupcake (1.5)或是更新发布的系统映像。

    特别指出1.0和1.1系统映像不支持NDK,这是由于在1.5发布中对toolchain和相关ABI做了改变。


1.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兼容共享库,这些库可以运行在ARM处理器上的Android1.5平台(及更高版本)。

- 拷贝生成共享库到应用程序工程路径的正确位置,那么它们将被自动添加到你的最后(和已签名)的.apk文件中。

- 在以后的NDK修订中,我们打算提供工具通过一个远程的gdb连接来帮助调试你的本地代码以及更多的源/符号信息。
   

此外,Android NDK规定:

- 一套交叉工具链(编译器,连接器等),可以产生本地的ARM二进制文件在Linux,OS X和Windows操作系统运用(使用Cygwin )
   

- 一套系统头符合于Android平台支持的稳定本地API列表。这相当于定义都保证支持所有更高版本的平台。
   
  
    重要的:
    请记住,在以后的更新和发布的平台,大多数在Android系统映像的本地系统库并没有固定,可能会被彻底地改变,甚至删除。

- 一个编译系统,它允许开发者编写很短的编译文件来描述哪些代码是需要编译的,并且怎么样编译。该编译系统处理所有的多如毛发的工具/平台/处理器/ABI的细节。
    此外,更新后的NDK,可以添加支持更多的工具,平台,系统接口,而无需改变开发编译文件(以下有更详细的介绍)。


2.不是Android NDK的目标:
--------------------------

NDK不是用来编写通用的运行在Android设备上的本地代码。特别指出,你的应用程序仍然应该用JAVA语言来编写,处理Android系统事件,应避免弹出"应用程序没有响应"对话框或处理Android应用

程序的生命周期。

但是请注意,NDK适于有可能采用本地代码编写一个复杂的应用程序与一个小的用于启动/停止的“应用程序封装”。

强烈建议很好的理解JNI,因为许多业务在这种环境下需要的具体动作来自于开发者,而不需要特定的本地代码。这些包括:

- 不能通过本地指针直接访问VM对象的内容。例如,你不能安全地获取一个指针对应一个字符串对象的16位字符数组在循环中的迭代。

- 需要明确提到管理本地代码时,要保持VM对象同JNI调用间的句柄。
   


NDK仅提供系统头,它针对Android平台支持的一套非常受限制的本地APIs和库。虽然一个典型Android系统映像包含许多本地共享库,这些共享库应该考虑
执行的细节,这些细节可能在已经发布的平台和更新之间被彻底改变。


如果一个Android系统库不是NDK头直接支持的,那么应用程序不应仅是可用而依赖它,否则在下一个空中系统更新多种设备后他们将不能使用。

选定的系统库将逐步地添加到一套稳定NDK的API中。


3.NDK开发实践:
---------------------------------

这里有一个非常粗略的概述指导你怎样使用Android NDK开发本地代码:

1/ 运行build/host-setup.sh配置NDK

2/ 放置你的代码到目录 sources/<mysrc>

3/ 编写sources/<mysrc>/Android.mk文件描述你的代码给NDK编译系统

4/ 编写apps/<myapp>/Application.mk文件描述你需要NDK编译系统编译的应用程序和本地代码

5/ 在NDK顶级目录中运行"make app=<myapp>"编译你的本地代码。
译者注:5/是在Cygwin中执行。

如果编译成功,最后一步将拷贝共享库到你的应用程序工程根目录。然后你就可以通过正常手段生成最后的.apk文件。

现在,一些更为详细的信息:


3.1 配置NDK:
- - - - - - - - - - - - - -

按照docs/INSTALL.TXT文件中描述安装NDK后,你应该运行'build/host-setup.sh'脚本来配置NDK。


这个脚本是用来探测你的主机系统并确认一些先决条件。
然后将生成一个配置文件(如:out/host/config-host.mk),它将在随后的NDK编译过程中使用到。

在某些情况下,这可能指示你为开发平台去下载一个包含预编译工具的二进制压缩文件,然后将它解压缩到NDK根目录。
这个提示应包含足够的信息让你做到这一点。


如果你忘记了这一步,那么在尝试使用NDK编译的时候将产生错误信息,这些信息将告诉你该怎么做。

3.2 放置C和C++代码:
- - - - - - - - - - - - - - - - -

NDK编译系统预定你的资源在顶级目录'sources'下可见。你应首先创建如下目录:
      $NDK/sources/<mysrc>/

你可以按照你想要的目录结构,灵活自由组织'sources'下的内容,这个目录名和结构将不影响最后生成的应用程序包,因此你不必使用不真实的独特的名字,
如:com.<mycompany>.<myproject>作为应用程序包名。

针对记录,NDK来自'sources/samples'目录,该目录自身包含多个简单模块的子目录。


请注意,C和C++源是支持的。默认C++文件扩展名是NDK支持的'.cpp',但是其他扩展名也能被很好地处理(详见docs/ANDROID-MK.TXT文件)。

可以存储你的源文件在不同的位置,只要你创建$NDK/sources/<mysrc>为一个符号链接。进行适当的操作,NDK编译系统必须能够找到来自$NDK/sources下的源文件和编译脚本。


3.3 编写Android.mk编译脚本:
- - - - - - - - - - - - - - - - - - - - - -

Android.mk文件是一个小编译脚本,你编写来描述源文件给NDK编译系统。它们的语法在文件docs/ANDROID-MK.TXT中有详细描述。

简而言之,NDK组织源文件进入"modules",这里每个模块可以是下列之一:

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

你能定义几个模块在一个单独的Android.mk文件中,或者你能编写几个Android.mk文件,每个文件定义一个单独的模块。

全部Android.mk文件在其他编译发生前被编译系统解析。
请注意,一个单独的Android.mk可以被编译系统解析多次,因此不要认为某些变量在它们中没有定义。

By default, the NDK will look for all files that match the following:
默认情况下, NDK将寻找匹配下列的所有文件:

   $NDK/sources/*/Android.mk

如果你想要定义Android.mk到子目录,你应明确地在顶级Android.mk文件中包含它们。这有一个帮助函数可以做到,如,使用:

   include $(call all-subdir-makefiles)
  

这将包含全部在当前编译文件路径下子目录中的全部Android.mk文件。


3.4 编写Application.mk编译文件:
- - - - - - - - - - - - - - - - - - - - - - -

虽然一个Android.mk文件描述模块给编译系统了,但是,你还需要编写一个Application.mk文件描述应用程序以及应用程序需要的模块。
该文件必须位于:

$NDK/apps/<myapp>/Application.mk

凡是<myapp>是一个应用程序的简短描述名称,将被用于调用NDK编译(并且不会进入最后APK文件)。
该文件用于提供给NDK编译下列内容:

- Android应用程序工程路径的位置。

- 应用程序需要的NDK模块的列表。
    这应该是一个真正的'共享库'模块的列表。

- 可选信息,如判断你要发布或者是调整编译,指定C或C++编译标志等。

- 计划:具体平台/处理器的清单,你想要的明确目标(当前仅支持一个)。

Application.mk文件的语法非常简单并且在docs/APPLICATION-MK.TXT文件中有描述。

你可以定义几个Application.mk文件建立同一个应用程序的不同编译,例如:

$NDK/apps/release/Application.mk
$NDK/apps/debug/Application.mk


3.5 调用NDK编译系统:
- - - - - - - - - - - - - - - - - -

在命令行,进入NDK顶级目录,然后使用以下命令调用编译系统:

   make APP=<myapp>

这里的‘make’是指GNU Make,并且<myapp>是一个'$NDK/apps/'中子目录的名称。

这将试图建立相关的全部模块选择,Application.mk文件列出最终共享库,如果编译成功,
将拷贝共享库到你的应用程序工程根目录(请注意:unstripped 版本可能是为保留调试目的,因此没有必要拷贝unstripped二进制到设备)。
译者注:unstripped不知道该如何翻译,故保留。


4. 调试支持:
- - - - - - - - - - - -

调试本地代码采用NDK的初始版本仍然很粗略。

请注意:我们计划在NDK的更新中让调试变得更简单,这一切无需改变你的源,Android.mk和Application.mk文件。
来自: http://hi.baidu.com/rocklad/blog/item/c35898db22bf60d1b7fd4878.html

你可能感兴趣的:(Android NDK概述)