面向英特尔® 架构 (IA) 创建和移植基于 NDK 的 Android* 应用

目标

本文旨在向初学者介绍如何为英特尔® 架构 (IA) 设备创建本机(基于 NDK)Android* 应用。我们还将介绍如何将为其它架构设备创建的 NDK Android 应用移植到英特尔® 架构设备上。我们将简要介绍两个场景。一个是展示创建基于 NDK 的基本 Android* 应用的整个过程;另一个是展示移植一个现有的基于 NDK 的 Android 应用以供英特尔® 架构设备使用的简单过程。

目录

1. 简介

2. 为基于 IA 的设备创建基于 NDK 的 Android 应用 – 简单应用介绍

a. 创建默认 Android 项目
b. 从 Java 源代码中调用本地代码
c. 利用 javah 生成本地代码的 JNI 头文件桩 (header stub)
d. 利用面向 IA 的 NDK 构建本地代码
e. 重新构建、安装和运行面向 IA 的 Android NDK

3. 利用 x86 NDK 工具集将现有的 NDK 应用移植到基于 IA 的设备

4. 总结

简介

利用原生开发套件 (NDK) 工具集可向 Android 应用添加本地代码。通过充分利用该工具集的特性,开发人员能够重复利用传统代码(适合于低级硬件的代码)或区分他们的应用。否则,开发人员将不能或不能很好地完成这一工作

本文对如何从头至尾面向 IA 创建基于 NDK 的应用进行了基本介绍,还介绍了将现有的基于 NDK 的应用移植到基于 IA 的设备的简单使用案例。我们将详细介绍简单的应用开发场景以展示该过程。

我们假设您已经安装了 Android 开发环境(包括 Android SDK 和 Android NDK)并配置了模拟器-x86 以测试应用。如欲了解更多信息,请参考英特尔网站上的“Android 社区”部分。为了使我们的开发环境尽量简单,我们将在大多数情况下使用 Linux* 命令行工具。

为基于 IA 的设备创建基于 NDK 的 Android 应用 – 简单应用介绍

假设我们手头上有一些利用 C 和汇编语言来解析 CPUID(有关 CPUID 的更多信息,请参考 http://en.wikipedia.org/wiki/CPUID* 的传统代码。以下列出了“传统”示例 C 代码 cpuid.c 的源代码(仅供演示之用)。

我们将从 Android 应用中调用 cpuid_parse(仅供演示之用 - cpuid_parse 函数需要预先分配的缓冲器),并显示该应用中的输出结果。

以下详细介绍了如何从头至尾创建 Android 应用以及如何使用上述传统本地代码。

1. 创建默认的 Android 项目

Android SDK 包含用于为典型的 hello world 应用生成默认项目结构的命令行工具。首先,我们将创建一个默认项目,然后修改 Java 源代码以添加 JNI 调用和本地代码。

在以上屏幕截图中,我们首先创建了一个称作“labs/lab2”的目录,并利用“android”命令行工具生成默认项目。我们将 API 级别指定为 android-15,并利用软件包 com.example.cpuid 将我们的应用命名为“CPUIdApp”。

然后,我们利用“ant”命令行工具在调试模式下构建项目,并利用“adb”命令进行安装(或重新安装,如果项目存在于模拟器或目标设备上)。我们假设您已经连接了模拟器或设备,且该模拟器或设备是执行“adb devices”命令后输出结果中唯一列出的设备。

以下是完成上述流程后 ICS 版的 Android x86 模拟器的屏幕截图。

单击该应用,您将看到该应用默认的 hello world 输出内容。下面,我们将对该应用进行修改以利用本地代码。

2. 从 java 源代码中调用本地代码

默认的 android 项目会为典型的 hello world 项目生成包含特定包命令空间(如 com.example.cpuid)的 java 源代码。以下屏幕截图显示了为主 java 源文件生成的源代码。

要在 java 源文件中使用本地 c/c++ 代码,我们首先需要宣告 JNI 调用并加载本地库,如以下屏幕截图中以黄色突出显示的框所示。

正如在宣告过程中看到的那样,本地调用返回了一个我们可在 java 源代码中任意位置使用的 java 字符串。如以上屏幕截图所示,我们修改了 TextView 以显示我们通过本地调用获得的字符串。该字符串在框中以红色突出显示。

以上是在 Android App Java 源代码中宣告和使用 JNI 本地调用的一个非常简单的案例。接下来,我们将使用“javah”工具为本地代码生成 JNI 头文件桩 (header stub),并添加或修改本地代码以与 JNI 原生头文件相符。

3. 利用“javah”生成本地代码的 JNI 头文件桩 (header stub)

现在,我们该修改本地代码以与 JNI 调用规范相符。“javah”还能帮助我们基于 Java 源文件自动生成适当的 JNI 头文件桩 (header stub)。要生成头文件,“javah”工具需要编译过的 Java 类文件。因此,我们利用“ant”工具快速生成 java 类文件,如以下屏幕截图所示(“ant debug”)。

我们还利用“javah”生成 ini 头文件,如屏幕截图中所示(第二个以黄色突出显示的框)。此举将基于 Java 类创建一个“ini”目录和头文件桩 (header stub)。以下屏幕截图显示了生成的 JNI 本地头文件桩 (native header stub)。

接下来,我们为以上生成的头文件创建相应的 C 源文件(“com_example_cpuid_CPUIdApp.c”)。以下列出了源代码。

然后,我们调用本地代码 cpuid_parse 并返回 JNI 字符串形式的解析缓冲器 (parsed buffer)。现在,我们可随时利用 x86 NDK 工具集来编译本地代码。

4. 利用面向 x86 的 NDK 构建本地代码

如欲了解有关如何安装和使用面向 IA 的 NDK 的更多信息,请参考英特尔网站上的 Android 社区部分 (http://software.intel.com/zh-cn/android/articles/android-ndk-for-intel-architecture)。

Android NDK 工具集利用一个编译系统来编译本地代码。该编译系统需要一个 android 特有的自定义 make 文件“Android.mk”才能在项目的“ini”文件夹中显示。Android.mk 指定了所有需要编译的本地 C/C++ 源代码、头文件和构建类型(如 shared_library)。

以下是 Android make 针对我们的项目(“jni/Android.mk”)列出的本地代码。

这是一个包含 2 C 源文件的简单场景,指定构建一个共享库。

现在,我们可以发送“ndk-build APP_ABI=x86”命令来构建我们的本地代码,并生成共享库。Android 编译系统还提供了另一个补充性 make 文件“Application.mk”,我们可利用该文件来指定其它配置选项。例如,我们可以指定 Application.mk 文件中所有受支持的 ABI,ndk-build 命令将生成本地共享库,以针对所有架构。

以上屏幕截图显示面向 x86 的本地代码编译成功,还显示了正在生成和安装的共享库。现在,我们可随时重新构建 Android 应用,并在 x86 模拟器或目标设备上安装/运行该应用。

5. 重新构建、安装和运行面向 IA 的 Android NDK

我们可以利用“ant debug clean”命令来清理旧的构建文件,并再次发送“ant debug”命令以开始完全重新构建 Android 项目。利用“adb”在目标设备或 x86 模拟器上重新安装该应用,如以下屏幕截图所示。

以下屏幕截图显示了 x86 模拟器中的应用图标,以及在 x86 模拟器中运行应用的输出结果。

我们已经从头至尾成功构建了基于 NDK 的 android 应用。

利用 x86 NDK 工具集将现有的 NDK 应用移植到基于 IA 的设备

包含本地代码的 Android 应用通常采用标准项目结构,其中“ini”文件夹用于存放原生源文件和相应的 Android.mk/Application.mk 构建文件。上一节中,我们介绍了一个包含本地源代码和相应 Android.mk 文件的简单例子。

利用 Android NDK 工具集,我们可以一次指定 Application.mk 文件中的所有目标 ABI,并自动生成所有目标 ABI 的本地共享库。Android 编译系统会自动打包 APK 中的所有目标本地库。安装时,Android 包管理器会根据目标架构仅安装相应的本地库。

我们可以调用“ndk-build”或在 Application.mk 中指定目标 ABI。

APP_ABI := all

OR

APP_ABI := armeabi armeabi-v7a x86

如欲了解更多信息,请参考 http://developer.android.com/sdk/ndk/index.html

要利用当前并不面向 x86 的本地代码来移植现有的 Android 应用,我们需要修改应用以支持 IA,这一过程在大多数情况下很简单(如上所述) - 除非该应用使用了架构特有的汇编语言或结构。可能存在其它问题,如内存对齐或平台特有的指令用途 (instructions usage)。详情请参考 http://software.intel.com/zh-cn/android/articles/ndk-android-application-porting-methodologies

总结

本文介绍了如何面向 IA 创建和移植基于 NDK 的 Android 应用。我们介绍了详细过程,以从头至尾演示面向 IA 创建基于 NDK 的应用的全过程。我们还介绍了 NDK 工具集提供的将现有的基于 NDK 的 Android 应用移植到目标 IA 的简单过程。

声明

英特尔是英特尔公司在美国和其它国家(地区)的商标

本文件中包含关于英特尔产品的信息。本文不代表英特尔公司或其它机构向任何人明确或隐含地授予任何知识产权。除相关产品的英特尔销售条款与条件中列明之担保条件以外,英特尔公司不对销售和/或使用英特尔产品做出其它任何明确或隐含的担保,包括对适用于特定用途、适销性,或不侵犯任何专利、版权或其它知识产权的担保。

“关键业务应用”是指当英特尔产品发生故障时,可能会直接或间接地造成人员伤害或死亡的应用。如果您针对此类关键业务应用购买或使用英特尔产品,您应当对英特尔进行赔偿,保证因使用此类关键业务应用而造成的产品责任、人员伤害或死亡索赔中直接或间接发生的所有索赔成本、损坏、费用以及合理的律师费不会对英特尔及其子公司、分包商和分支机构,以及相关的董事、管理人员和员工造成损害,无论英特尔及其分包商在英特尔产品或其任何部件的设计、制造或警示环节是否出现疏忽大意的情况。

英特尔有权随时更改产品的规格和描述而毋需发出通知。设计者不应信赖任何英特产品所不具有的特性,设计者亦不应信赖任何标有“保留权利”或“未定义”说明或特性描述。英特尔保留今后对其定义的权利,对于因今后对其进行修改所产生的冲突或不兼容性概不负责。此处提供的信息可随时改变而毋需通知。请勿使用本信息来对某个设计做出最终决定。

文中所述产品可能包含设计缺陷或错误,已在勘误表中注明,这可能会使产品偏离已经发布的技术规范。英特尔提供最新的勘误表备索。

订购产品前,请联系您当地的英特尔销售办事处或分销商了解最新技术规范。

如欲获得本文或其它英特尔文献中提及的带订单编号的文档副本,可致电 1-800-548-4725,或访问:http://www.intel.com/design/literature.htm
*其他的名称和品牌可能是其他所有者的资产。

版权所有 © 2012 英特尔公司。保留所有权利