Android-NDK处理用户交互事件
在 android_main(struct android_app* state)函数里面设置输入事件处理函数:
state->onInputEvent = &handleInput;//设置输入事件的处理函数,如触摸响应
函数介绍:
AMotionEvent_getX():以屏幕左上角为原点,是绝对坐标
AMotionEvent_getY():以屏幕左上角为原点,是绝对坐标
AMotionEvent_getPointerCount();多点触摸函数,返回触摸的点数量,跟硬件有关系
#include <jni.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h> #include <EGL/egl.h>
#include <GLES/gl.h>
#include <vector>
#include <string>
#include <map>
#include <android/sensor.h>
#include <android/log.h>
#include <android_native_app_glue.h> #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__)) /**
* Our saved state data.
*/
struct saved_state {
float angle;
int32_t x;
int32_t y;
}; /**
* Shared state for our app.
*/
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;
}; class float3
{
public:
float x,y,z;
};
std::vector<float3> g_arVertex;
/**
* Initialize an EGL context for the current display.
*/
static int engine_init_display(struct engine* engine) {
// initialize OpenGL ES and EGL /*
* Here specify the attributes of the desired configuration.
* Below, we select an EGLConfig with at least 8 bits per color
* component compatible with on-screen windows
*/
const EGLint attribs[] =
{
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, ,
EGL_GREEN_SIZE, ,
EGL_RED_SIZE, ,
EGL_NONE
};
EGLint w, h, dummy, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, , ); /* Here, the application chooses the configuration it desires. In this
* sample, we have a very simplified selection process, where we pick
* the first EGLConfig that matches our criteria */
eglChooseConfig(display, attribs, &config, , &numConfigs); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
* As soon as we picked a EGLConfig, we can safely reconfigure the
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(engine->app->window, , , format); surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
context = eglCreateContext(display, config, NULL, NULL); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return -;
} eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h); engine->display = display;
engine->context = context;
engine->surface = surface;
engine->width = w;
engine->height = h;
engine->state.angle = ; // Initialize GL state.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
glViewport(,,w,h);
glOrthof(,w,h,,-,); return ;
} /**
* Just the current frame in the display.
*/
static void engine_draw_frame(struct engine* engine) {
if (engine->display == NULL) {
// No display.
return;
} // Just fill the screen with a color.
glClearColor(((float)engine->state.x)/engine->width, engine->state.angle,
((float)engine->state.y)/engine->height, );
glClear(GL_COLOR_BUFFER_BIT); glEnableClientState(GL_VERTEX_ARRAY);
if(g_arVertex.size() >= )
{
glColor4f(,,,);
glVertexPointer(,GL_FLOAT,,&g_arVertex[]);
glDrawArrays(GL_LINE_STRIP,,g_arVertex.size());
} eglSwapBuffers(engine->display, engine->surface);
} /**
* Tear down the EGL context currently associated with the display.
*/
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 = ;
engine->display = EGL_NO_DISPLAY;
engine->context = EGL_NO_CONTEXT;
engine->surface = EGL_NO_SURFACE;
} /**
* Process the next input event.
*/
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
{
struct engine* engine = (struct engine*)app->userData; int32_t evtType = AInputEvent_getType(event);
switch(evtType)
{
case AINPUT_EVENT_TYPE_KEY:
break; case AINPUT_EVENT_TYPE_MOTION:
{
switch(AInputEvent_getSource(event))
{
case AINPUT_SOURCE_TOUCHSCREEN:
{
int32_t id = AMotionEvent_getAction(event);
switch(id)
{
case AMOTION_EVENT_ACTION_MOVE:
{
size_t cnt = AMotionEvent_getPointerCount(event);
for( int i = ;i < cnt; ++ i )
{
float x = AMotionEvent_getX(event,i);
float y = AMotionEvent_getY(event,i);
char szBuf[];
LOGI("x = %f y = %f",x,y);
float3 pt;
pt.x = x;
pt.y = y;
pt.z = ;
g_arVertex.push_back(pt);
} }
break;
case AMOTION_EVENT_ACTION_DOWN:
{
float x = AMotionEvent_getX(event,);
float y = AMotionEvent_getY(event,);
char szBuf[];
LOGI("x = %f y = %f",x,y);
float3 pt;
pt.x = x;
pt.y = y;
pt.z = ;
g_arVertex.push_back(pt);
}
break;
case AMOTION_EVENT_ACTION_UP:
break;
}
}
break;
case AINPUT_SOURCE_TRACKBALL:
break;
}
}
break;
} if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
{
engine->animating = ;
engine->state.x = AMotionEvent_getX(event, );
engine->state.y = AMotionEvent_getY(event, );
return ;
}
return ;
} /**
* Process the next main command.
*/
static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
struct engine* engine = (struct engine*)app->userData;
switch (cmd) {
case APP_CMD_SAVE_STATE: break;
case APP_CMD_INIT_WINDOW:
// The window is being shown, get it ready.
if (engine->app->window != NULL) {
engine_init_display(engine);
}
break;
case APP_CMD_TERM_WINDOW:
// The window is being hidden or closed, clean it up.
engine_term_display(engine);
break;
case APP_CMD_GAINED_FOCUS: break;
case APP_CMD_LOST_FOCUS: break;
}
} /**
* This is the main entry point of a native application that is using
* android_native_app_glue. It runs in its own thread, with its own
* event loop for receiving input events and doing other things.
*/
void android_main(struct android_app* state) {
struct engine engine; // Make sure glue isn't stripped.
app_dummy(); memset(&engine, , sizeof(engine));
state->userData = &engine;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
engine.app = state; // Prepare to monitor accelerometer
engine.sensorManager = ASensorManager_getInstance();
engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
ASENSOR_TYPE_ACCELEROMETER); if (state->savedState != NULL) {
// We are starting with a previous saved state; restore from it.
engine.state = *(struct saved_state*)state->savedState;
} int ident, events;
struct android_poll_source* source; while (true)
{
while ((ident = ALooper_pollAll(, NULL, &events, (void**)&source)) >= )
{
if (source != NULL)
source->process(state, source); if (state->destroyRequested != )
return;
} engine_draw_frame(&engine);
} }
效果如图所示。
APK下载:下载
Android-NDK处理用户交互事件的更多相关文章
- Android - 和其他APP交互 - 把用户带到其他app
Android的重要功能之一就是app可以根据要执行的操作让用户启动另外一个app.例如,app有一个商业地址然后想要在地图上显示,并不需要在app中加一个显示地图的activity,可以直接用Int ...
- Android SDK上手指南 3:用户交互
在这篇教程中,我们将对之前所添加的Button元素进行设置以实现对用户点击的检测与响应.为了达成这一目标,我们需要在应用程序的主Activity类中略微涉及Java编程内容.如果大家在Java开发方面 ...
- event代表事件的状态,专门负责对事件的处理,它的属性和方法能帮助我们完成很多和用户交互的操作;
IE的event和其他的标准DOM的Event是不一样的,不同的浏览器事件的冒泡机制也是有区别 IE:window.event.cancelBubble = true;//停止冒泡window.eve ...
- Android NDK开发入门实例
AndroidNDK是能使Android应用开发者把从c/c++编译而来的本地代码嵌入到应用包中的一系列工具的组合. 注意: AndroidNDK只能用于Android1.5及以上版本中. I. An ...
- Android NDK 和 OpenCV 整合开发总结(3)
Android NDK 和 OpenCV 整合开发总结(3) http://hujiaweibujidao.github.io/blog/2013/11/18/android-ndk-and-open ...
- Android NDK开发Crash错误定位[转]
使用 ndk-stack 的时候需要你的 lib 编译为 debug版的,通常需要下面的修改: 1. 修改 android.mk,增加,为 LOCAL_CFLAGS 增加 -g 选项 2. 修改 ap ...
- 五毛的cocos2d-x学习笔记06-处理用户交互
前几篇感觉自己在写教育文章,╮(╯▽╰)╭.今天换成开发者的口吻,毕竟我也是在边学边写博客. 处理用户交互包括:单点触摸.多点触摸.事件传递.传感器.物理按键等部分. 单点触摸: 触摸事件传递顺序 o ...
- Threejs 的场景查看 - 几个交互事件库助你方便查看场景
Threejs 的场景查看 - 几个交互事件库助你方便查看场景 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...
- C# 通过服务启动窗体(把窗体添加到服务里)实现用户交互的windows服务[转发]
由于个人需要,想找一个键盘记录的程序,从网上下载了很多,多数都是需要注册的,另外也多被杀软查杀.于是决定自己写一个,如果作为一个windows应用程序,可以实现抓取键盘的记录.想要实现随系统启动的话, ...
随机推荐
- spring boot打包后windows启动乱码
事情的起因什么的就不多表了,直接进入主题... 项目都要上线了,结果发现使用 idea mvn install之后的 jar在windows下启动乱码,而使用idea启动却没有问题!!! 这是神马情况 ...
- PAT甲 1046. Shortest Distance (20) 2016-09-09 23:17 22人阅读 评论(0) 收藏
1046. Shortest Distance (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue The ...
- EBS-DBA 维护
--查询表空间使用率: SELECT UPPER(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小(M)", ...
- delphi_xe开发ios环境的安装与设置
http://wenku.baidu.com/link?url=NE3xJOZiLppdxCbXJX3W0vyLHv6uA_U8uamjx9NJIIcxnfuC2P9eWx3d6Xwco-ugS8G ...
- ABP 基础设施层——集成 NHibernate
本文翻译自ABP的官方教程<NHibernate Integration>,地址为:http://aspnetboilerplate.com/Pages/Documents/NHibern ...
- 四、创建覆盖网络--Flannel
Flannel是 CoreOS 团队针对 Kubernetes 设计的一个覆盖网络(Overlay Network)工具,其目的在于帮助每一个使用 Kuberentes 的 CoreOS 主机拥有 ...
- Spark Structured Stream 2
❤Limitations of DStream API Batch Time Constraint application级别的设置. 不支持EventTime event time 比process ...
- Oracle数据库中 to_date()与24小时制表示法及mm分钟的显示
一.在使用Oracle的to_date函数来做日期转换时,时候也许会直接的采用“yyyy-MM-dd HH:mm:ss”的格式作为格式进行转换,但是在Oracle中会引起错误:“ORA 01810 ...
- 记录.NET Core部署到Linux之发布项目到Linux(2)
1.选择文件夹发布项目到本地,通过Xftp上传文件到/home/wwwroot下:下面具体介绍下 2.通过Xftp直接拖拽压缩包到linux下,通过命令cd /home/wwwroot目录下;然后输入 ...
- 自定义Asp.net core——日志记录
本文我将演示如何定制日志记录.默认的日志记录仅仅向控制台或者debug窗口输出日志,这样可以满足一些情况,但是你可能还需要把日志记录到一个磁盘文件或者数据库,或者你想为记录额外的信息.这样的场景你就需 ...