原生Activity开发实战:Native Activity示例解析
【免费下载链接】ndk-samples 项目地址: https://gitcode.com/gh_mirrors/ndks/ndk-samples
本文深入解析Android NDK开发中的Native Activity架构,涵盖其核心组件设计、生命周期管理机制、OpenGL ES上下文初始化、加速度计数据处理等关键技术。通过详细分析代码示例,展示如何完全使用C/C++构建高性能Android应用,包括EGL配置、传感器集成、渲染优化等最佳实践。
Native Activity架构与生命周期管理
Native Activity是Android NDK开发中的核心组件,它允许开发者完全使用C/C++代码构建Android应用,无需编写Java代码。这种架构为高性能图形应用、游戏和实时处理应用提供了强大的底层支持。本文将深入解析Native Activity的架构设计和生命周期管理机制。
Native Activity架构设计
Native Activity的核心架构基于Android的Native App Glue库,它提供了一个完整的C/C++接口来管理Android应用的生命周期。整个架构可以分为以下几个关键组件:
1. 核心数据结构
struct engine {
struct android_app* app; // Android应用上下文
ASensorManager* sensorManager; // 传感器管理器
const ASensor* accelerometerSensor;// 加速度传感器
ASensorEventQueue* sensorEventQueue;// 传感器事件队列
int animating; // 动画状态标志
EGLDisplay display; // EGL显示对象
EGLSurface surface; // EGL表面
EGLContext context; // EGL上下文
int32_t width; // 屏幕宽度
int32_t height; // 屏幕高度
struct saved_state state; // 应用状态保存
};
这个engine结构体是整个应用的核心,它封装了所有必要的状态和资源,包括图形渲染上下文、传感器管理和应用状态。
2. 应用状态管理
struct saved_state {
float angle; // 旋转角度
int32_t x; // X坐标
int32_t y; // Y坐标
};
状态保存机制允许应用在配置变更(如屏幕旋转)或后台运行时保持用户界面的连续性。
生命周期管理机制
Native Activity的生命周期管理通过一系列预定义的事件命令来实现,这些命令在engine_handle_cmd函数中处理:
生命周期事件处理表
| 事件命令 | 触发时机 | 典型处理操作 |
|---|---|---|
APP_CMD_SAVE_STATE | 应用即将进入后台 | 保存当前状态到内存 |
APP_CMD_INIT_WINDOW | 窗口创建完成 | 初始化EGL显示和OpenGL ES |
APP_CMD_TERM_WINDOW | 窗口销毁 | 清理EGL资源 |
APP_CMD_GAINED_FOCUS | 应用获得焦点 | 启用传感器监听 |
APP_CMD_LOST_FOCUS | 应用失去焦点 | 禁用传感器监听,停止动画 |
生命周期流程图
关键生命周期回调实现
1. 窗口初始化与销毁
case APP_CMD_INIT_WINDOW:
if (engine->app->window != nullptr) {
engine_init_display(engine); // 初始化显示
engine_draw_frame(engine); // 绘制第一帧
}
break;
case APP_CMD_TERM_WINDOW:
engine_term_display(engine); // 清理显示资源
break;
2. 焦点管理
case APP_CMD_GAINED_FOCUS:
if (engine->accelerometerSensor != nullptr) {
ASensorEventQueue_enableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
// 设置60FPS的事件率
ASensorEventQueue_setEventRate(engine->sensorEventQueue,
engine->accelerometerSensor,
(1000L / 60) * 1000);
}
break;
case APP_CMD_LOST_FOCUS:
if (engine->accelerometerSensor != nullptr) {
ASensorEventQueue_disableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
}
engine->animating = 0; // 停止动画
engine_draw_frame(engine); // 绘制最后一帧
break;
3. 状态保存与恢复
case APP_CMD_SAVE_STATE:
engine->app->savedState = malloc(sizeof(struct saved_state));
*((struct saved_state*)engine->app->savedState) = engine->state;
engine->app->savedStateSize = sizeof(struct saved_state);
break;
输入事件处理机制
Native Activity使用统一的输入事件处理接口:
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
auto* engine = (struct engine*)app->userData;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
engine->animating = 1;
engine->state.x = AMotionEvent_getX(event, 0);
engine->state.y = AMotionEvent_getY(event, 0);
return 1; // 事件已处理
}
return 0; // 事件未处理
}
主循环架构
Native Activity的主循环采用事件驱动模式:
最佳实践与性能优化
- 资源管理: 在
APP_CMD_TERM_WINDOW中彻底释放EGL资源,避免内存泄漏 - 状态保存: 使用轻量级的序列化机制保存关键状态,避免存储大量数据
- 传感器使用: 只在获得焦点时启用传感器,节省电池电量
- 线程安全: 确保所有OpenGL操作都在渲染线程中执行
常见问题与解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 黑屏或无显示 | EGL初始化失败 | 检查EGL配置和窗口有效性 |
| 应用崩溃 | 内存访问越界 | 验证指针和内存分配 |
| 传感器无响应 | 权限问题或焦点丢失 | 检查权限并在获得焦点时启用 |
| 状态恢复失败 | 状态数据结构不匹配 | 确保状态保存和恢复的一致性 |
Native Activity的架构设计充分体现了Android系统对原生开发的支持,通过精心设计的生命周期管理机制,开发者可以构建出高性能、低延迟的移动应用。掌握这些核心概念对于深入理解Android NDK开发至关重要。
OpenGL ES 2.0上下文初始化与渲染
在Android Native Activity开发中,OpenGL ES 2.0的上下文初始化与渲染是构建高性能图形应用的核心环节。本节将深入解析Native Activity示例中如何正确初始化EGL上下文、配置OpenGL ES状态以及实现高效的渲染循环。
EGL上下文初始化流程
EGL(Embedded-System Graphics Library)是OpenGL ES与原生窗口系统之间的接口层,负责管理图形上下文、表面和显示设备。在Native Activity中,EGL初始化遵循以下标准流程:
关键配置参数
在EGL初始化过程中,需要指定一系列配置属性来定义渲染表面的特性:
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, // 窗口表面类型
EGL_BLUE_SIZE, 8, // 蓝色分量8位
EGL_GREEN_SIZE, 8, // 绿色分量8位
EGL_RED_SIZE, 8, // 红色分量8位
EGL_NONE // 属性列表结束
};
配置选择策略
示例代码展示了智能的配置选择算法,优先选择8位RGB无深度的配置,如果没有找到则使用第一个可用配置:
for (; i < numConfigs; i++) {
auto& cfg = supportedConfigs[i];
EGLint r, g, b, d;
if (eglGetConfigAttrib(display, cfg, EGL_RED_SIZE, &r) &&
eglGetConfigAttrib(display, cfg, EGL_GREEN_SIZE, &g) &&
eglGetConfigAttrib(display, cfg, EGL_BLUE_SIZE, &b) &&
eglGetConfigAttrib(display, cfg, EGL_DEPTH_SIZE, &d) &&
r == 8 && g == 8 && b == 8 && d == 0) {
config = supportedConfigs[i];
break;
}
}
if (i == numConfigs) {
config = supportedConfigs[0]; // 回退到第一个配置
}
OpenGL ES状态配置
成功创建EGL上下文后,需要配置OpenGL ES的渲染状态。示例中展示了几个关键的状态设置:
| 状态函数 | 参数 | 作用描述 |
|---|---|---|
glHint | GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST | 设置透视校正为最快模式 |
glEnable | GL_CULL_FACE | 启用面剔除,提高渲染效率 |
glShadeModel | GL_SMOOTH | 启用平滑着色 |
glDisable | GL_DEPTH_TEST | 禁用深度测试(2D渲染) |
// 初始化GL状态
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
渲染循环实现
渲染帧的核心函数engine_draw_frame展示了基本的颜色填充渲染:
static void engine_draw_frame(struct engine* engine) {
if (engine->display == nullptr) {
return; // 无显示设备时返回
}
// 基于触摸位置设置清除颜色
glClearColor(((float)engine->state.x) / engine->width,
engine->state.angle,
((float)engine->state.y) / engine->height,
1);
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
eglSwapBuffers(engine->display, engine->surface); // 交换缓冲区
}
颜色计算逻辑
示例中使用了动态的颜色计算方式,将触摸坐标映射到颜色值:
- 红色分量:
engine->state.x / width(X坐标归一化) - 绿色分量:
engine->state.angle(旋转角度) - 蓝色分量:
engine->state.y / height(Y坐标归一化)
这种设计使得屏幕颜色会随着用户触摸位置的变化而动态改变,提供了直观的交互反馈。
资源清理与生命周期管理
正确的资源管理是Native Activity开发中的重要环节。示例提供了完整的清理函数:
static void engine_term_display(struct engine* engine) {
if (engine->display != EGL_NO_DISPLAY) {
eglMakeCurrent(engine->display, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (engine->context != EGL_NO_CONTEXT) {
eglDestroyContext(engine->display, engine->context);
}
if (engine->surface != EGL_NO_SURFACE) {
eglDestroySurface(engine->display, engine->surface);
}
eglTerminate(engine->display);
}
// 重置所有显示相关状态
engine->animating = 0;
engine->display = EGL_NO_DISPLAY;
engine->context = EGL_NO_CONTEXT;
engine->surface = EGL_NO_SURFACE;
}
错误处理与日志输出
示例中包含了完善的错误处理机制和日志输出:
#define LOGI(...) \
((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) \
((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
// 在初始化过程中输出OpenGL信息
auto opengl_info = {GL_VENDOR, GL_RENDERER, GL_VERSION, GL_EXTENSIONS};
for (auto name : opengl_info) {
auto info = glGetString(name);
LOGI("OpenGL Info: %s", info);
}
这种设计帮助开发者快速定位问题,了解运行时的硬件和驱动信息。
性能优化建议
基于示例代码的实现,可以总结出以下性能优化策略:
- 配置选择优化: 优先选择无深度缓冲的配置以减少内存占用
- 状态管理: 一次性设置所有需要的OpenGL状态,避免频繁状态切换
- 资源复用: 在应用生命周期内保持EGL上下文,避免重复初始化
- 异步渲染: 使用双缓冲机制确保平滑的渲染体验
通过深入理解EGL上下文初始化流程和OpenGL ES状态管理,开发者可以构建出高性能、稳定的图形应用程序。Native Activity示例提供了一个优秀的起点,展示了Android NDK开发中图形编程的最佳实践。
加速度计数据读取与处理实现
在Android NDK开发中,加速度计数据的读取与处理是传感器应用开发的核心技术之一。本节将深入分析NDK示例中加速度计数据的完整处理流程,从传感器初始化到数据滤波再到可视化渲染的全过程。
传感器初始化与配置
加速度计传感器的初始化是整个数据读取流程的起点。在NDK中,我们使用Android Sensor API的C语言接口来管理传感器设备。
// 获取传感器管理器实例
ASensorManager *AcquireASensorManagerInstance(void) {
typedef ASensorManager *(*PF_GETINSTANCEFORPACKAGE)(const char *name);
void *androidHandle = dlopen("libandroid.so", RTLD_NOW);
PF_GETINSTANCEFORPACKAGE getInstanceForPackageFunc =
(PF_GETINSTANCEFORPACKAGE)dlsym(androidHandle,
"ASensorManager_getInstanceForPackage");
if (getInstanceForPackageFunc) {
return getInstanceForPackageFunc(kPackageName);
}
typedef ASensorManager *(*PF_GETINSTANCE)();
PF_GETINSTANCE getInstanceFunc =
(PF_GETINSTANCE)dlsym(androidHandle, "ASensorManager_getInstance");
assert(getInstanceFunc);
return getInstanceFunc();
}
// 初始化传感器
void init(AAssetManager *assetManager) {
sensorManager = AcquireASensorManagerInstance();
assert(sensorManager != NULL);
// 获取加速度计传感器
accelerometer = ASensorManager_getDefaultSensor(sensorManager,
ASENSOR_TYPE_ACCELEROMETER);
assert(accelerometer != NULL);
// 创建事件队列
looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
accelerometerEventQueue = ASensorManager_createEventQueue(
sensorManager, looper, LOOPER_ID_USER, NULL, NULL);
// 启用传感器并设置采样率
ASensorEventQueue_enableSensor(accelerometerEventQueue, accelerometer);
ASensorEventQueue_setEventRate(accelerometerEventQueue, accelerometer,
SENSOR_REFRESH_PERIOD_US);
}
传感器参数配置表
在加速度计数据采集中,合理的参数配置对数据质量和性能至关重要。以下是示例中使用的关键参数:
| 参数名称 | 值 | 说明 |
|---|---|---|
| SENSOR_HISTORY_LENGTH | 100 | 历史数据缓存长度 |
| SENSOR_REFRESH_RATE_HZ | 100 | 采样频率(Hz) |
| SENSOR_REFRESH_PERIOD_US | 10000 | 采样周期(微秒) |
| SENSOR_FILTER_ALPHA | 0.1 | 低通滤波器系数 |
数据读取与滤波处理
加速度计原始数据通常包含噪声,需要进行滤波处理以获得平滑的数据流。示例中采用指数移动平均(EMA)滤波器进行实时数据平滑。
// 数据更新与滤波处理
void update() {
ALooper_pollAll(0, NULL, NULL, NULL);
ASensorEvent event;
float alpha = SENSOR_FILTER_ALPHA;
// 读取传感器事件
while (ASensorEventQueue_getEvents(accelerometerEventQueue, &event, 1) > 0) {
// 应用低通滤波器
sensorDataFilter.x = alpha * event.acceleration.x +
(1.0f - alpha) * sensorDataFilter.x;
sensorDataFilter.y = alpha * event.acceleration.y +
(1.0f - alpha) * sensorDataFilter.y;
sensorDataFilter.z = alpha * event.acceleration.z +
(1.0f - alpha) * sensorDataFilter.z;
}
// 更新数据缓冲区
sensorData[sensorDataIndex] = sensorDataFilter;
sensorData[SENSOR_HISTORY_LENGTH + sensorDataIndex] = sensorDataFilter;
sensorDataIndex = (sensorDataIndex + 1) % SENSOR_HISTORY_LENGTH;
}
数据结构设计
为了高效存储和处理加速度计数据,示例中设计了专门的数据结构:
数据可视化渲染
处理后的加速度计数据通过OpenGL ES进行可视化渲染,实时显示三轴加速度的变化趋势:
void render() {
glClearColor(0.f, 0.f, 0.f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
// 设置顶点位置属性
glEnableVertexAttribArray(vPositionHandle);
glVertexAttribPointer(vPositionHandle, 1, GL_FLOAT, GL_FALSE, 0, xPos);
// 渲染X轴加速度数据(黄色)
glEnableVertexAttribArray(vSensorValueHandle);
glVertexAttribPointer(vSensorValueHandle, 1, GL_FLOAT, GL_FALSE,
sizeof(AccelerometerData),
&sensorData[sensorDataIndex].x);
glUniform4f(uFragColorHandle, 1.0f, 1.0f, 0.0f, 1.0f);
glDrawArrays(GL_LINE_STRIP, 0, SENSOR_HISTORY_LENGTH);
// 渲染Y轴加速度数据(洋红色)
glVertexAttribPointer(vSensorValueHandle, 1, GL_FLOAT, GL_FALSE,
sizeof(AccelerometerData),
&sensorData[sensorDataIndex].y);
glUniform4f(uFragColorHandle, 1.0f, 0.0f, 1.0f, 1.0f);
glDrawArrays(GL_LINE_STRIP, 0, SENSOR_HISTORY_LENGTH);
// 渲染Z轴加速度数据(青色)
glVertexAttribPointer(vSensorValueHandle, 1, GL_FLOAT, GL_FALSE,
sizeof(AccelerometerData),
&sensorData[sensorDataIndex].z);
glUniform4f(uFragColorHandle, 0.0f, 1.0f, 1.0f, 1.0f);
glDrawArrays(GL_LINE_STRIP, 0, SENSOR_HISTORY_LENGTH);
}
生命周期管理
Android应用的生命周期管理对传感器资源的使用至关重要,需要在适当的时机启用和禁用传感器:
// 暂停时禁用传感器
void pause() {
ASensorEventQueue_disableSensor(accelerometerEventQueue, accelerometer);
}
// 恢复时重新启用传感器
void resume() {
ASensorEventQueue_enableSensor(accelerometerEventQueue, accelerometer);
ASensorEventQueue_setEventRate(accelerometerEventQueue, accelerometer,
SENSOR_REFRESH_PERIOD_US);
}
数据处理流程
整个加速度计数据的处理流程可以概括为以下步骤:
性能优化建议
在实际开发中,加速度计数据处理需要注意以下性能优化点:
- 合理的采样率:根据应用需求选择适当的采样频率,避免不必要的资源消耗
- 环形缓冲区:使用环形缓冲区存储历史数据,减少内存分配开销
- 批处理操作:在可能的情况下批量处理传感器事件,提高处理效率
- 线程管理:传感器数据处理应在适当的线程中进行,避免阻塞UI线程
通过上述实现,开发者可以构建高效、稳定的加速度计数据采集和处理系统,为各种传感器应用提供可靠的数据基础。
纯C++ Android应用开发最佳实践
在Android NDK开发中,纯C++应用开发需要遵循一系列最佳实践来确保代码的性能、可维护性和跨平台兼容性。Native Activity示例为我们展示了如何构建一个完全基于C++的Android应用,下面我们来深入探讨其中的关键实践。
项目结构与构建系统配置
一个良好的项目结构是成功开发的基础。Native Activity示例采用了CMake作为构建系统,这是Android Studio推荐的现代构建工具。
cmake_minimum_required(VERSION 3.4.1)
# 构建native_app_glue静态库
add_library(native_app_glue STATIC
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
# 设置编译标志
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall -Werror")
# 导出ANativeActivity_onCreate符号
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
add_library(native-activity SHARED main.cpp)
target_include_directories(native-activity PRIVATE
${ANDROID_NDK}/sources/android/native_app_glue)
target_link_libraries(native-activity
android
native_app_glue
EGL
GLESv1_CM
log)
关键实践:
- 使用CMake而不是传统的ndk-build
- 明确指定C++标准(如-std=gnu++11)
- 启用警告和错误检查(-Wall -Werror)
- 正确配置符号导出
应用生命周期管理
Native Activity的生命周期管理通过android_native_app_glue库实现,它封装了Android应用的生命周期回调:
struct engine {
struct android_app* app;
ASensorManager* sensorManager;
const ASensor* accelerometerSensor;
ASensorEventQueue* sensorEventQueue;
int animating;
EGLDisplay display;
EGLSurface surface;
EGLContext context;
int32_t width;
int32_t height;
struct saved_state state;
};
生命周期管理最佳实践:
- 状态保存与恢复
case APP_CMD_SAVE_STATE:
engine->app->savedState = malloc(sizeof(struct saved_state));
*((struct saved_state*)engine->app->savedState) = engine->state;
engine->app->savedStateSize = sizeof(struct saved_state);
break;
- 资源管理
static void engine_term_display(struct engine* engine) {
if (engine->display != EGL_NO_DISPLAY) {
eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
if (engine->context != EGL_NO_CONTEXT) {
eglDestroyContext(engine->display, engine->context);
}
if (engine->surface != EGL_NO_SURFACE) {
eglDestroySurface(engine->display, engine->surface);
}
eglTerminate(engine->display);
}
}
图形渲染与OpenGL ES集成
Native Activity示例展示了如何正确初始化和使用OpenGL ES进行渲染:
渲染循环最佳实践:
static void engine_draw_frame(struct engine* engine) {
if (engine->display == nullptr) return;
glClearColor(((float)engine->state.x) / engine->width,
engine->state.angle,
((float)engine->state.y) / engine->height, 1);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(engine->display, engine->surface);
}
输入处理与传感器集成
正确处理用户输入和设备传感器是Native应用的关键:
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
auto* engine = (struct engine*)app->userData;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
engine->animating = 1;
engine->state.x = AMotionEvent_getX(event, 0);
engine->state.y = AMotionEvent_getY(event, 0);
return 1;
}
return 0;
}
传感器管理最佳实践:
case APP_CMD_GAINED_FOCUS:
if (engine->accelerometerSensor != nullptr) {
ASensorEventQueue_enableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
ASensorEventQueue_setEventRate(engine->sensorEventQueue,
engine->accelerometerSensor,
(1000L / 60) * 1000);
}
break;
case APP_CMD_LOST_FOCUS:
if (engine->accelerometerSensor != nullptr) {
ASensorEventQueue_disableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
}
break;
内存管理与错误处理
纯C++开发需要特别注意内存管理和错误处理:
#define LOGI(...) \
((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) \
((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
// 使用现代C++内存管理
std::unique_ptr<EGLConfig[]> supportedConfigs(new EGLConfig[numConfigs]);
assert(supportedConfigs);
错误处理模式:
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return -1;
}
跨版本兼容性处理
处理不同Android版本的API差异:
ASensorManager* AcquireASensorManagerInstance(android_app* app) {
if (!app) return nullptr;
// 处理不同版本的传感器管理器获取方式
typedef ASensorManager* (*PF_GETINSTANCEFORPACKAGE)(const char* name);
void* androidHandle = dlopen("libandroid.so", RTLD_NOW);
// ... 版本兼容性处理代码
}
性能优化建议
| 优化领域 | 建议做法 | 效果 |
|---|---|---|
| 渲染性能 | 使用双缓冲和VSync | 减少画面撕裂 |
| 内存使用 | 及时释放资源 | 避免内存泄漏 |
| 电池寿命 | 只在获得焦点时启用传感器 | 延长电池使用时间 |
| 启动速度 | 延迟初始化非关键资源 | 快速启动应用 |
调试与日志记录
建立完善的调试体系:
// 检查OpenGL系统信息
auto opengl_info = {GL_VENDOR, GL_RENDERER, GL_VERSION, GL_EXTENSIONS};
for (auto name : opengl_info) {
auto info = glGetString(name);
LOGI("OpenGL Info: %s", info);
}
通过遵循这些最佳实践,开发者可以构建出高性能、稳定且易于维护的纯C++ Android应用。Native Activity示例为我们提供了一个优秀的参考实现,展示了如何正确处理Android系统的各种复杂场景。
总结
Native Activity为Android高性能图形应用提供了完整的C/C++开发解决方案。通过精心设计的架构和生命周期管理,开发者可以构建低延迟、高效率的移动应用。掌握EGL初始化、OpenGL状态管理、传感器数据处理等核心技术,结合合理的资源管理和性能优化策略,是成功开发纯C++ Android应用的关键。本文的示例和分析为深入理解Android NDK开发提供了实用指导。
【免费下载链接】ndk-samples 项目地址: https://gitcode.com/gh_mirrors/ndks/ndk-samples
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



