NDK

来源:互联网 发布:淘宝上注册商标靠谱吗 编辑:程序博客网 时间:2024/06/05 17:13

原文链接:https://developer.android.com/ndk/guides/android_mk.html
NDK 能够在Android应用中使用原生代码对于想执行以下一项或多项的开发者特别有用:

  • 在平台之间移植其应用
  • 重复使用现有库

主要组件:

  • ndk-build:ndk-build脚本用于在NDK中心启动构建脚本。
    • 自动探测您的开发系统和应用项目文件以确定要构建的内容。
    • 生成二进制文件
    • 将二进制文件复制到应用的项目路径。
  • Java
    Android构建过程从Java来源生成.dex文件,这些文件是Android OS在Dalvik虚拟机(“DVM”)中运行的文件。即使您的应用根本未包含任何Java源代码,构建过程仍会生成原生组件在其中运行的.dex可执行文件。
    开发Java组件时,使用native关键字只是以原生代码形式实现的方法。例如:
`public native int add(int  x, int  y);`
  • 原生共享库
    NDK从原生代码构建这些库或.so文件。

  • 原生静态库

  • Java原生接口(JNI):JNI是Java和C++组件用以互相沟通的接口。
  • 应用二进制界面
    ABI 可以非常精确地定义应用的机器代码在运行时如何与系统交互。 NDK 根据这些定义构建 .so 文件。 不同的 ABI 对应不同的架构:NDK 包含对 ARMEABI(默认)、MIPS 和 x86 的 ABI 支持。
  • 清单:如果您要编写没有Java组件的应用,必须在清单中声明NativeActivity类。原生 Activity 和应用在使用native_activity.h接口下提供了如何执行此操作的详细信息。

在使用ndk-build脚本构建时以及使用ndk-gdb脚本调试时才需要。

  • Android.mk:必须在jni文件夹内创建Android.mk配置文件。ndk-build脚本将查看此文件,其中定义了模块及其名称、要编译的源文件、版本标志以及要链接的库。
  • Application.mk:此文件枚举并描述您的应用需要的模块。这些信息包括:
    • 用于针对特定平台进行编译的ABI。
    • 工具链
    • 要包含的标准库

流程:

为Android开发原生应用的一般流程如下:

  1. 设计应用,确定要在Java中实现的部分,以及要以原生代码形式实现的部分。
    注:虽然可以完全避免Java,但您可能发现,Android Java框架对于包括控制显示和UI在内的任务很有用。

  2. 像创建任何其他Android项目一样创建一个Android应用项目

  3. 如果要编写纯原生应用,请在AndroidManifest.xml中生命NativeActivity类。如需了解详细信息,请参阅原生 Activity 和应用
  4. 在“JNI”目录中创建一个描述原生库的Android.mk文件,包括名称、标志、链接库和要编译的源文件。
  5. 或者,也可以创建一个配置目标ABI工具链、发行/调试模式和STL的Application.mk文件。对于其中任何您未指明的项目,将分别使用一下默认值:
    • ABI:armeabi
    • 工具链:GCC 4.8
    • 模式:发行
    • STL: 系统
  6. 将原生来源置于项目的jni目录下。
  7. 使用ndk-build编译原生(.so、.a)库。
  8. 构建Java组件,生成可执行.dex文件
  9. 将所有内容封装到一个APK文件中,包含.so、.dex以及应用所需的其他文件。

原生Activity和应用

Android SDK提供帮助程序类NativeActivity,可用于写入完全原生的Activity。NativeActivity可处理Android框架与原生代码之间的通信,因此您不必为其创建子类或调用方法,只需在AndroidManifest.xml文件中声明要设为原生的应用,然后开始创建原生应用。
使用NativeActivity的Android应用仍会在其自己的虚拟机中运行,与其他应用以沙盒分隔。因此,您仍可通过 JNI 访问 Android 框架 API。 但在某些情况下 – 例如对于传感器、输入事件和资产– NDK 提供可以使用的原生界面,而无需通过 JNI 调用。 如需了解有关此类支持的详细信息,请参阅 Android NDK 原生 API。

无论是否要开发原生 Activity,我们都建议使用传统 Android 构建工具创建项目。 这样有助于确保 Android 应用的构建和封装都使用正确的结构。

Android NDK 为实现原生 Activity 提供两个选项:

  • native_activity.h 标头定义 NativeActivity 类的原生版本。 其中包含创建原生 Activity 所需的的回调接口和数据结构。 由于应用的主线程处理回调,因此不得阻止回调的实现。 否则可能收到 ANR(应用未响应)错误,因为主线程在回调返回之前会无响应。
  • android_native_app_glue.h 文件定义基于 native_activity.h 接口构建的静态帮助程序库。它将派生另一个线程,用于处理事件循环中的回调或输入事件。 将这些事件移至单独的线程可防止任何回调阻止您的主线程。

/sources/android/native_app_glue/android_native_app_glue.c 来源也可用,允许您修改实现。

如需了解有关如何使用此静态库的详细信息,请检查原生 Activity 示例应用及其文档。 /sources/android/native_app_glue/android_native_app_glue.h 文件中的注释也提供其他阅读材料。

使用 native_activity.h 接口

要使用 native_activity.h 接口实现原生 Activity,请执行以下操作:

  1. 在项目的根目录中创建一个 jni/ 目录。此目录用于存储所有原生代码。
  2. 在 AndroidManifest.xml 文件中声明原生 Activity。 因为您的应用没有 Java 代码,所以将
    android:hasCode 设为 false。
<application android:label="@string/app_name" android:hasCode="false">

必须将 Activity 标记的 android:name 属性设置为 NativeActivity。

<activity android:name="android.app.NativeActivity"            android:label="@string/app_name">

注:可以为 NativeActivity 创建子类。如果创建子类,请使用子类的名称,而不是 NativeActivity。
meta-data 标记的 android:value 属性指定共享库的名称,其中包含应用的入口点(例如 C/C++ main),省略 lib 前缀和 .so 后缀。

        <meta-data android:name="android.app.lib_name"            android:value="native-activity" />            <intent-filter>              <action android:name="android.intent.action.MAIN" />              <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>          </activity>        </application>      </manifest>

3.创建用于原生 Activity 的文件,并实现 ANativeActivity_onCreate 变量中指定的函数。应用在原生
Activity 启动时会调用此函数。 此函数类似于 C/C++ 中的 main,用于接收 ANativeActivity
结构的指针,其中包含您需要写入的各个回调实现的函数指针。在 ANativeActivity->callbacks
中设置回调实现的适用回调函数指针。
4.将 ANativeActivity->instance 字段设置为要使用的特定数据的任何实例的地址。

5.实现您希望 Activity 在启动时执行的任何其他操作。

6.实现您在 ANativeActivity->callbacks 中设置的其余回调。如需了解何时调用回调的详细信息,请参阅管理 Activity 生命周期。
7. 开发应用的其余部分。
8.在项目的 jni/ 目录中创建 Android.mk file,向构建系统描述您的原生模块。 如需了解详细信息,请参阅 Android.mk。
9.在创建 Android.mk 文件后,使用 ndk-build 命令编译原生代码。

$ cd <path>/<to>/<project>$ <ndk>/ndk-build

10.像平常一样构建和安装 Android 项目。如果原生代码在 jni/ 目录中,构建脚本会自动将从它构建的 .so 文件封装到 APK 中。

原创粉丝点击