NDK Native-Activity示例启动崩溃求助及Vulkan触摸事件处理咨询
一、解决Native-Activity示例启动崩溃问题
崩溃原因分析
抛出的ClassNotFoundException显示找不到androidx.startup.InitializationProvider,说明项目缺少AndroidX App Startup组件依赖,或构建配置中该组件被错误排除。
解决方案
添加App Startup依赖
在模块级build.gradle(或build.gradle.kts)的dependencies块中添加:implementation "androidx.startup:startup-runtime:1.1.1"添加完成后点击Sync Now同步项目,确保依赖正确引入。
禁用App Startup(无需该组件时)
若你的Native Activity应用不需要App Startup功能,可在AndroidManifest.xml中移除对应Provider声明:<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.native_activity"> <application> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" tools:node="remove" /> </application> </manifest>注意需在manifest根标签中添加
tools命名空间。清理构建缓存
点击Android Studio菜单栏File->Invalidate Caches...,勾选Invalidate and Restart,清理旧构建缓存并重启IDE,避免缓存导致的依赖加载问题。检查NDK版本兼容性
确保使用的NDK版本与示例兼容,建议使用r25及以上稳定版本。可通过File->Project Structure->SDK Location设置NDK路径和版本。
二、Vulkan应用C++侧触摸事件处理方法
Native Activity通过android_app结构体提供事件回调机制,触摸事件属于AINPUT_EVENT_TYPE_MOTION类型,处理步骤如下:
1. 设置事件回调
在android_main函数中,为android_app绑定输入事件处理函数:
#include <android/native_activity.h> #include <android/input.h> #include <android/log.h> // 存储触摸状态,可根据需求扩展 struct TouchState { float x = 0.0f; float y = 0.0f; bool is_touched = false; } g_touch_state; static int handle_input_event(struct android_app* app, AInputEvent* event); static void handle_app_cmd(struct android_app* app, int32_t cmd); void android_main(struct android_app* app) { // 初始化Vulkan、窗口等资源... // 绑定事件回调 app->onInputEvent = handle_input_event; app->onAppCmd = handle_app_cmd; // 主循环 int events; struct android_poll_source* source; while (!app->destroyRequested) { while (ALooper_pollAll(0, nullptr, &events, (void**)&source) >= 0) { if (source != nullptr) { source->process(app, source); } } // 执行Vulkan渲染逻辑,可使用g_touch_state中的触摸数据更新场景 // render_frame(); } // 清理Vulkan等资源... }
2. 实现触摸事件处理函数
在handle_input_event中解析触摸动作类型、坐标等信息:
static int handle_input_event(struct android_app* app, AInputEvent* event) { if (AInputEvent_getType(event) != AINPUT_EVENT_TYPE_MOTION) { return 0; // 非触摸事件交给系统处理 } int action = AMotionEvent_getAction(event); int action_type = action & AMOTION_EVENT_ACTION_MASK; int pointer_idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; int pointer_id = AMotionEvent_getPointerId(event, pointer_idx); // 获取Android坐标系下的触摸坐标(左上角为原点) float x = AMotionEvent_getX(event, pointer_idx); float y = AMotionEvent_getY(event, pointer_idx); switch (action_type) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: g_touch_state.is_touched = true; g_touch_state.x = x; g_touch_state.y = y; __android_log_print(ANDROID_LOG_INFO, "Touch", "Pointer %d down at (%.2f, %.2f)", pointer_id, x, y); break; case AMOTION_EVENT_ACTION_MOVE: // 遍历所有触摸点处理多点触摸 int pointer_count = AMotionEvent_getPointerCount(event); for (int i = 0; i < pointer_count; ++i) { int pid = AMotionEvent_getPointerId(event, i); float px = AMotionEvent_getX(event, i); float py = AMotionEvent_getY(event, i); __android_log_print(ANDROID_LOG_INFO, "Touch", "Pointer %d moved to (%.2f, %.2f)", pid, px, py); if (pid == pointer_id) { g_touch_state.x = px; g_touch_state.y = py; } } break; case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_POINTER_UP: case AMOTION_EVENT_ACTION_CANCEL: g_touch_state.is_touched = false; __android_log_print(ANDROID_LOG_INFO, "Touch", "Pointer %d up", pointer_id); break; } return 1; // 表示已处理该事件 } static void handle_app_cmd(struct android_app* app, int32_t cmd) { // 处理应用生命周期事件 switch (cmd) { case APP_CMD_DESTROY: app->destroyRequested = true; break; // 其他生命周期命令处理... } }
3. 转换触摸坐标到Vulkan坐标系
Android触摸坐标系以屏幕左上角为原点,Vulkan默认以窗口左下角为原点,需进行转换:
// 假设window_width和window_height是Vulkan交换链的宽高 float vulkan_x = x; float vulkan_y = app->window->height - y; // 转换到NDC(归一化设备坐标,范围[-1,1]) float ndc_x = (vulkan_x / app->window->width) * 2.0f - 1.0f; float ndc_y = (vulkan_y / app->window->height) * 2.0f - 1.0f;
转换后的坐标可用于更新Vulkan场景交互逻辑,比如旋转3D模型、移动UI元素等。
内容的提问来源于stack exchange,提问作者gmmo

