Android NDK 原生 API

Android NDK 会提供一组随着新的 Android API 级别的后续发布而逐渐添加的原生标头和共享库文件。本页将介绍这些标头和文件,并将其与特定 Android API 级别进行对应。

使用原生 API

请执行以下两个基本步骤的操作,以便让您的应用使用 NDK 提供的库:

  1. 在您的代码中添加与您想使用的库关联的标头。
  2. 通知编译系统您的原生模块需要在加载时链接库。
    • 如果您使用的是 ndk-build:将原生库添加到您 Android.mk 文件中的 LOCAL_LDLIBS 变量中。例如,要链接 /system/lib/libfoo.so,请添加以下这行代码:
    •     LOCAL_LDLIBS := -lfoo
          

      要列出多个库,请使用空格作为分隔符。要详细了解如何使用 LOCAL_LDLIBS 变量,请参阅 Android.mk

    • 如果您使用的是 CMake:请按照向您的项目添加 C 和 C++ 代码中的说明操作。
对于所有 API 级别,编译系统都将自动链接标准 C 库和 C++ 库。您无需在设置 LOCAL_LDLIBS 时明确添加这些库。

NDK 通常会为新的 Android 版本提供新的标头和库。如需获取 Android 发行版引入的原生 API 的列表,请查看下方的表 1。这些文件位于 NDK 安装根目录下的 sysroot/usr/include 中。

下表显示了支持 NDK 的 API 级别和 Android 平台版本之间的对应关系。要详细了解 Android API 级别,请参阅什么是 API 级别?

表 1. Android 版本引入的关键原生 API 支持摘要。

支持 NDK 的 API 级别 Android 平台版本 关键原生 API 包括
3 1.5 C 标准库 (libc/libm) #include ...
C++ #include ...
Java 原生接口 #include <jni.h>
Android 日志记录 API #include <android/log.h>
Zlib #include <zlib.h>
动态链接器 #include <dlfcn.h>
4 1.6 OpenGL ES 1.x #include <GLES/gl.h>
#include <GLES/glext.h>
5 2.0 - 2.1.x OpenGL ES 2.0 #include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
8 2.2 Android 位图 API #include <android/bitmap.h>
9 2.3 - 3.0.x EGL #include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
OpenSL ES #include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Platform.h>
#include <SLES/OpenSLES_Android.h>
#include <SLES/OpenSLES_AndroidConfiguration.h>
原生应用 API 事件循环:
#include <android/looper.h>

输入事件:
#include <android/input.h>
#include <android/keycodes.h>

传感器事件:
#include <android/sensor.h>

窗口/表面管理:
#include <android/rect.h>
#include <android/window.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>

资产:
#include <android/asset_manager.h>

配置:
#include <android/configuration.h>

OBB 文件:
#include <android/storage_manager.h>

#include <android/obb.h>

原生 Activity:
#include <android/native_activity.h>
12 3.1.x
13 3.2
14 4.0 - 4.0.2 OpenMAX AL #include <OMXAL/OpenMAXAL.h>
#include <OMXAL/OpenMAXAL_Platform.h>
#include <OMXAL/OpenMAXAL_Android.h>
15 4.0.3、4.0.4
16 4.1、4.1.1
17 4.2、4.2.2
18 4.3 OpenGL ES 3.0 #include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
19 4.4、4.4w
21 5.0、5.1 OpenGL ES 3.1 #include <GLES3/gl31.h>
#include <GLES3/gl3ext.h>
原生媒体 API #include <media/NdkMediaCodec.h>
#include <media/NdkMediaCrypto.h>
#include <media/NdkMediaDrm.h>
#include <media/NdkMediaError.h>
#include <media/NdkMediaExtractor.h>
#include <media/NdkMediaFormat.h>
#include <media/NdkMediaMuxer.h>
23 6.0 原生跟踪 API #include <android/trace.h>
24 7.0 - 7.1.1 Vulkan #include <vulkan/vulkan.h>
原生相机 API #include <camera/NdkCameraCaptureSession.h>
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraError.h>
#include <camera/NdkCameraManager.h>
#include <camera/NdkCameraMetadata.h>
#include <camera/NdkCameraMetadataTags.h>
#include <camera/NdkCaptureRequest.h>
原生 choreographer API #include <android/choreographer.h>
原生多网络 API #include <android/multinetwork.h>
OpenGL ES 3.2 #include <GLES3/gl32.h>
#include <GLES3/gl3ext.h>
原生媒体 API #include <media/NdkImage.h>
#include <media/NdkImageReader.h>
26 8.0 AAudio API #include <aaudio/AAudio.h>
硬件缓冲区 API #include <android/hardware_buffer.h>
#include <android/hardware_buffer_jni.h>>
共享内存 API #include <android/sharedmem.h>
27 8.1 神经网络 API #include <android/NeuralNetworks.h>
共享内存 JNI API #include <android/hardware_buffer.h>
28 9.0 SurfaceTexture API #include <android/surface_texture.h>

原生 API 亮点

Android API 级别 3

C 库

标准 C 库标头可通过其常用名称(例如:<stdlib.h><stdio.h>)获取。请注意,与 Linux 不同,在 Android 上不存在单独的 pthread 库和 rt 库。该功能包含在 libc 中。数学库在 libm 中保持独立,但由编译器自动添加。

动态链接器库

您可以使用 Android 动态链接器的 dlopen(3) 和 dlsym(3) 功能。此外,您还必须链接 libdl。例如:
    LOCAL_LDLIBS := -ldl
    

C++ 库

提供 C++17 支持。要详细了解 C++ 库支持,请参阅 C++ 库支持

Android 专属日志支持

<android/log.h> 包含各种不同的函数,应用可使用这些函数从原生代码向 logcat 发送日志消息。要详细了解这些定义,请参阅日志记录文档。一般而言,您应自行编写封装容器宏以使用此功能。如果您想要记录日志,请链接到 liblog。例如:
    LOCAL_LDLIBS := -llog
    

ZLib 压缩库

您可以通过添加 zlib.hzconf.h 来使用 Zlib 压缩库。此外,您还必须通过在 Android.mk 文件中添加以下这行代码,将您的原生模块链接到 /system/lib/libz.so

    LOCAL_LDLIBS := -lz
    

Android API 级别 4

NDK 提供了下列 API,供开发者开发在 Android 1.6 及更高版本系统映像上运行的原生代码。

OpenGL ES 1.x 库

标准 OpenGL ES 标头 <GLES/gl.h><GLES/glext.h> 包含从原生代码执行 OpenGL ES 1.x 渲染调用所需的声明。

要使用这些标头,请通过在您的 Android.mk 文件中添加以下这行代码,将您的原生模块链接到 /system/lib/libGLESv1_CM.so

    LOCAL_LDLIBS := -lGLESv1_CM
    

所有 Android 设备均支持 OpenGL ES 1.0,因为 Android 提供了支持 Open GL 1.0 且可在没有 GPU 的设备上使用的软件渲染程序。

只有具有所需 GPU 的 Android 设备才完全支持 OpenGL ES 1.1。应用可以查询 OpenGL ES 版本字符串和扩展字符串,以确定当前设备是否支持其需要的功能。要详细了解如何执行此查询,请参阅 OpenGL 规范中的 glGetString() 说明。

此外,您必须在清单文件中放置一个 <uses-feature> 标签,以指明您的应用所需的 OpenGL ES 版本。

EGL API 仅从 API 级别 9 开始提供。不过,您可以使用虚拟机来执行您从这些 API 获取的部分操作,包括表面构建和翻转。有关如何使用 GLSurfaceView 的示例,请参阅 GLSurfaceView 简介

san-angeles 示例应用提供了一个示例,展示如何执行这些操作,从而在原生代码中渲染每个帧。此示例是出色的 San Angeles Observation 演示程序的小型 Android 端口。

Android API 级别 5

NDK 提供了下列 API,供开发者开发在 Android 2.0 及更高版本系统映像上运行的原生代码。

OpenGL ES 2.0 库:

标准 OpenGL ES 2.0 标头 <GLES2/gl2.h><GLES2/gl2ext.h> 包含从原生代码执行 OpenGL ES 2.0 渲染调用所需的声明。这些渲染调用可提供利用 GLSL 语言定义并使用顶点和片段着色程序的功能。

要使用 OpenGL ES 2.0,请在 Android.mk 文件中添加以下这行代码,从而将您的原生模块链接到 /system/lib/libGLESv2.so

    LOCAL_LDLIBS := -lGLESv2
    

并非所有设备都支持 OpenGL ES 2.0。应用可以查询 OpenGL ES 版本字符串和扩展字符串,以确定当前设备是否支持其需要的功能。要详细了解如何执行此查询,请参阅 OpenGL 规范中的 glGetString() 说明。

此外,您必须在清单文件中放置一个 <uses-feature> 标签,以指明您的应用所需的 OpenGL ES 版本。要详细了解针对 <uses-feature> 的 OpenGL ES 设置,请参阅 OpenGL ES

hello-gl2 示例应用提供了一个基本示例,展示如何将 OpenGL ES 2.0 与 NDK 结合使用。

EGL API 仅从 API 级别 9 开始提供。不过,您可以使用虚拟机来执行您从这些 API 获取的部分操作,包括表面构建和翻转。有关如何使用 GLSurfaceView 的示例,请参阅 GLSurfaceView 简介

Android API 级别 8

NDK 提供了下列 API,供开发者开发在 Android 2.2 及更高版本系统映像上运行的原生代码。

jnigraphics

jnigraphics 库会显示一个基于 C 的接口,该接口可让原生代码以可靠方式访问 Java 位图对象的像素缓冲区。使用 jnigraphics 的工作流程如下:

  1. 使用 AndroidBitmap_getInfo() 从 JNI 检索信息,例如指定位图句柄的宽度和高度。
  2. 使用 AndroidBitmap_lockPixels() 锁定像素缓冲区并检索指向它的指针。这样做可确保像素在应用调用 AndroidBitmap_unlockPixels() 之前不会移动。
  3. 在原生代码中,对像素缓冲区进行相应的修改,以使其符合相应像素格式、宽度和其他特性。
  4. 调用 AndroidBitmap_unlockPixels() 来解锁缓冲区。

要使用 jnigraphics,请在您的源代码中添加 <bitmap.h> 标头,并通过在您的 Android.mk 文件中添加以下这行代码来链接到 jnigraphics

    LOCAL_LDLIBS += -ljnigraphics
    

有关此功能的其他详细信息,请参阅 <android/bitmap.h> 文件的注释。

Android API 级别 9

NDK 提供了下列 API,供开发者开发在 Android 2.3 及更高版本系统映像上运行的原生代码。

EGL

EGL 可提供用于分配和管理 OpenGLES 表面的原生平台接口。要详细了解其功能,请参阅 EGL 原生平台接口

EGL 可让您通过原生代码执行以下操作:

  • 列出支持的 EGL 配置。
  • 分配和释放 OpenGLES 表面。
  • 切换或翻转表面。

以下标头提供 EGL 功能:

  • <EGL/egl.h>:主要的 EGL API 定义。
  • <EGL/eglext.h>:与 EGL 扩展相关的定义。

要链接到系统的 EGL 库,请将以下这行代码添加到您的 Android.mk 文件中:

    LOCAL_LDLIBS += -lEGL
    

OpenSL ES

Android 原生音频处理基于 Khronos Group OpenSL ES 1.0.1 API。

标准 OpenSL ES 标头 <SLES/OpenSLES.h><SLES/OpenSLES_Platform.h> 包含从 Android 原生端执行音频输入和输出所需的声明。OpenSL ES 的 NDK 分发还提供 Android 专用扩展程序。要详细了解这些扩展程序,请参阅 <SLES/OpenSLES_Android.h><SLES/OpenSLES_AndroidConfiguration.h> 中的注释。

系统库 libOpenSLES.so 可实现公共原生音频函数。请向您的 Android.mk 文件中添加以下这行代码,从而链接到该库:

    LOCAL_LDLIBS += -lOpenSLES
    

要详细了解 OpenSL ES API,请参阅面向 Android 的 OpenSL ES

Android 原生应用 API

从 API 级别 9 开始,您可以使用原生代码(无需使用任何 Java 代码)编写整个 Android 应用。

注意:单纯使用原生代码编写应用并不足以让您的应用在虚拟机中运行。此外,您的应用仍必须通过 JNI 访问 Android 平台的大部分功能。

此版本提供下列原生标头:

要详细了解这些标头,请参阅 NDK API 参考文档以及标头本身的注释。此外,要详细了解编写原生应用这一较大的主题,请参阅原生 Activity 和应用

当您添加这些标头中的其中一个或多个时,您还必须链接到 libandroid.so 库。要链接到 libandroid.so,请在您的 Android.mk 文件中添加以下这行代码:

    LOCAL_LDLIBS += -landroid
    

Android API 级别 14

NDK 提供了下列 API,供开发者开发在 Android 4.0 及更高版本系统映像上运行的原生代码。

OpenMAX AL

Android 原生多媒体处理基于 Khronos Group OpenMAX AL 1.0.1 API。

标准 OpenMAX AL 标头 <OMXAL/OpenMAXAL.h><OMXAL/OpenMAXAL_Platform.h> 包含从 Android 原生端执行多媒体输出所需的声明。

OpenMAX AL 的 NDK 分发还提供 Android 专用扩展程序。要详细了解这些扩展程序,请参阅 <OMXAL/OpenMAXAL_Android.h> 中的注释。

系统库 libOpenMAXAL.so 可实现公共原生多媒体函数。要链接到此库,请在您的 Android.mk 文件中添加以下这行代码:

    LOCAL_LDLIBS += -lOpenMAXAL
    

要详细了解此主题,请参阅 $NDK/docs/openmaxal/index.html,其中 $NDK 是您的 NDK 安装的根目录。

OpenSL ES

针对此 Android API 级别的 OpenSL ES 支持增加了 PCM 支持。要详细了解 NDK 中的 OpenSL ES 支持,请参阅 OpenSL ES

Android API 级别 18

NDK 提供了下列 API,供开发者开发可在 Android 4.3(及更高版本)系统映像上运行的原生代码。

OpenGL ES 3.0

标准 OpenGL ES 3.0 标头 <GLES3/gl3.h><GLES3/gl3ext.h> 包含通过原生代码执行 OpenGL ES 3.0 渲染调用所需的声明。这些渲染调用可提供利用 GLSL 语言定义并使用顶点和片段着色程序的功能。

要使用 OpenGL ES 3.0,请在 Android.mk 文件中添加以下这行代码,从而将您的原生模块链接到 /system/lib/libGLESv3.so

    LOCAL_LDLIBS := -lGLESv3
    

并非所有设备都支持 OpenGL ES 3.0。应用可以查询 OpenGL ES 版本字符串和扩展字符串,以确定当前设备是否支持其需要的功能。要详细了解如何执行此查询,请参阅 OpenGL 规范中的 glGetString() 说明。

此外,您必须在清单文件中放置一个 <uses-feature> 标签,以指明您的应用所需的 OpenGL ES 版本。要详细了解针对 <uses-feature> 的 OpenGL ES 设置,请参阅 OpenGL ES

gles3jni 示例应用提供了一个基本示例,展示如何将 OpenGL ES 3.0 与 NDK 结合使用。

Android API 级别 21

NDK 提供了下列 API,供开发者开发可在 Android 4.3(及更高版本)系统映像上运行的原生代码。

OpenGL ES 3.1

标准 OpenGL ES 3.1 标头 <GLES3/gl31.h><GLES3/gl3ext.h> 包含从原生代码执行 OpenGL ES 3.1 渲染调用所需的声明。这些渲染调用可提供利用 GLSL 语言定义并使用顶点和片段着色程序的功能。

要使用 OpenGL ES 3.1,请通过在 Android.mk 文件中添加以下这行代码,从而将您的原生模块链接到 /system/lib/libGLESv3.so

    LOCAL_LDLIBS := -lGLESv3
    

并非所有设备都支持 OpenGL ES 3.1。应用可以查询 OpenGL ES 版本字符串和扩展字符串,以确定当前设备是否支持其需要的功能。要详细了解如何执行此查询,请参阅 OpenGL 规范中的 glGetString() 说明。

此外,您必须在清单文件中放置一个 <uses-feature> 标签,以指明您的应用所需的 OpenGL ES 版本。要详细了解针对 <uses-feature> 的 OpenGL ES 设置,请参阅 OpenGL ES

gles3jni 示例应用提供了一个基本示例,展示如何将 OpenGL ES 3.1 与 NDK 结合使用。

注意:Android 模拟器不支持 OpenGL ES 3.1 硬件模拟。要运行和测试使用此 API 的代码,您需要有一个其硬件可支持 OpenGL ES 3.1 的实际设备。

Android API 级别 23

NDK 引入了下列 API,供开发者开发在 Android 6.0 及更高版本系统映像上运行的原生代码。

跟踪

原生跟踪 API (<android/trace.h>) 采用 Java 编程语言,可提供效果等同 android.os.trace 方法的原生方法。此 API 通过将跟踪事件写入系统跟踪缓冲区,让您能够跟踪原生代码中的指定工作单元。接下来,您便可以使用 Systrace 工具来收集和分析跟踪事件。要详细了解如何使用此 API,请参阅原生跟踪

Android API 级别 24

NDK 引入了下列 API,供开发者开发在 Android 7.0 及更高版本系统映像上运行的原生代码。

Vulkan

Vulkan 是用于高性能三维图形渲染的低开销、跨平台 API,并且是一种由 Khronos Group 维护的开放式标准。标准 <vulkan/vulkan.h> 标头文件包含从原生代码执行 Vulkan 渲染调用所需的声明。

要详细了解如何在您的 Android 应用中使用 Vulkan,请参阅 API 文档。对于代码示例,请参阅 GitHub 上的 vulkan-basic-samplesandroid-vulkan-tutorials 项目。

相机

原生相机 API 采用 Java 编程语言,提供效果等同 android.hardware.camera2 类的原生类。您可利用原生相机 API,在原生代码中执行细粒度照片的拍摄及处理。与 Java camera2 API 不同,原生相机 API 不支持已弃用的相机 HAL 1.0 实现(即原生相机 API 中的可用相机列表不会列出达到 LEGACY 硬件级别的相机设备)。

Choreographer

原生 choreographer API (<android/choreographer.h>) 采用 Java 语言,可提供效果等同 android.view.Choreographer 类的原生类。您可利用原生 choreographer API,在原生代码中协调动画、输入和绘图的时间。此 API 有助于与 vsync 实现同步,对帧同步非常有用。有关如何使用 choreographer API 的示例,请参阅 GitHub 上 Teapots 示例项目中的 choreographer-30fps 目录。

多网络

原生多网络 API (<android/multinetwork.h>) 提供与 Android 5.0 中添加的 Java 多网络 API 相同功能的原生代码访问权限。

EGL

适用于 Android API 级别 24 的 EGL 支持增加了对以下扩展的支持:

要详细了解 NDK 中的 EGL 支持,请参阅 EGL

OpenGL ES 3.2

标准 OpenGL ES 3.2 标头 <GLES3/gl32.h><GLES3/gl3ext.h> 包含从原生代码执行 OpenGL ES 3.2 渲染调用所需的声明。

要使用 OpenGL ES 3.2,请通过在 Android.mk 文件中添加以下这行代码,将您的原生模块链接到 /system/lib/libGLESv3.so

    LOCAL_LDLIBS := -lGLESv3
    

并非所有设备都支持 OpenGL ES 3.2。应用可以查询 OpenGL ES 版本字符串和扩展字符串,以确定当前设备是否支持其需要的功能。要详细了解如何执行此查询,请参阅 OpenGL 规范中的 glGetString() 说明。

此外,您必须在清单文件中放置一个 <uses-feature> 标签,以指明您的应用所需的 OpenGL ES 版本。要详细了解针对 <uses-feature> 的 OpenGL ES 设置,请参阅 OpenGL ES

Android API 级别 26

NDK 引入了下列 API,供开发者开发在 Android 8.0 及更高版本系统映像上运行的原生代码。

AAudio

NDK 为需要低延迟的高性能音频应用引入了 AAudio API (<aaudio/AAudio.h>)。使用 AAudio 的应用会在音频流中执行数据读写操作。AAudio 旨在提供比使用 OpenSL ES 更便捷的方式。要详细了解如何使用此 API,请参阅 AAudio 开发者指南

硬件缓冲区

NDK 引入了两个原生 API,以便您针对跨进程缓冲区管理创建自己的管道。

您可利用原生硬件缓冲区 API (<android/hardware_buffer.h>) 直接分配缓冲区,以针对跨进程缓冲区管理创建自己的管道。您可以分配 AHardwareBuffer 结构,并将其用于通过 eglGetNativeClientBufferANDROID 扩展获取 EGLClientBuffer 资源类型。您可将此缓冲区传递到 eglCreateImageKHR,以创建 EGLImage 资源类型,随后此资源类型可能会在支持的设备上通过 glEGLImageTargetTexture2DOES 与纹理绑定。此方法可用于创建可跨进程共享的纹理。

您可利用原生硬件缓冲区 JNI API (<android/hardware_buffer_jni.h>) 获取一个 HardwareBuffer 对象(该对象是一个 Parcelable),以便在两个不同进程之间传输。如此,您的应用可获得与 SurfaceFlinger 相似的功能(例如,在不同进程之间创建自己的缓冲区队列),而无需访问内部 Android API。

共享内存

共享内存 API (<android/sharedmem.h>) 是 Android 原生共享内存的封装容器,可用于进程间通信。创建共享内存后,系统会将文件描述符作为句柄返回。您可以使用 mmap() 完成文件描述符与进程内存空间的映射,从而访问共享内存中的内容。要移除映射,请调用 munmap()。文件描述符可通过 UNIX 网域套接字与其他进程进行交换。关闭相关文件描述符并移除所有进程中的所有内存映射后,系统会释放已分配的共享内存。

Android API 级别 27

NDK 引入了下列 API,供开发者开发在 Android 8.1 及更高版本系统映像上运行的原生代码。

Neural Networks API

Neural Networks API (<android/neuralnetworks.h>) 为应用提供适用于设备上机器学习操作的硬件加速功能。此 API 支持在设备上创建、编译和执行模型。应用通常不会直接使用 NNAPI;相反,API 将通过机器学习库、框架和工具进行调用,以便开发者在 Android 设备上训练并部署其模型。要了解详情,请参阅 Neural Networks API 开发者指南API 参考