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, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
EGLint w, h, dummy, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;

EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

eglInitialize(display, 0, 0);

/* 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, 1, &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, 0, 0, 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 -1;
}

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 = 0;

// Initialize GL state.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
glViewport(0,0,w,h);
glOrthof(0,w,h,0,-100,100);

return 0;
}

/**
* 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, 1);
glClear(GL_COLOR_BUFFER_BIT);

glEnableClientState(GL_VERTEX_ARRAY);
if(g_arVertex.size() >= 2)
{
glColor4f(1,1,1,1);
glVertexPointer(3,GL_FLOAT,0,&g_arVertex[0]);
glDrawArrays(GL_LINE_STRIP,0,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 = 0;
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 = 0 ;i < cnt; ++ i )
{
float x = AMotionEvent_getX(event,i);
float y = AMotionEvent_getY(event,i);
char szBuf[64];
LOGI("x = %f y = %f",x,y);
float3 pt;
pt.x = x;
pt.y = y;
pt.z = 0;
g_arVertex.push_back(pt);
}

}
break;
case AMOTION_EVENT_ACTION_DOWN:
{
float x = AMotionEvent_getX(event,0);
float y = AMotionEvent_getY(event,0);
char szBuf[64];
LOGI("x = %f y = %f",x,y);
float3 pt;
pt.x = x;
pt.y = y;
pt.z = 0;
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 = 1;
engine->state.x = AMotionEvent_getX(event, 0);
engine->state.y = AMotionEvent_getY(event, 0);
return 1;
}
return 0;
}

/**
* 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, 0, 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(0, NULL, &events, (void**)&source)) >= 0)
{
if (source != NULL)
source->process(state, source);

if (state->destroyRequested != 0)
return;
}

engine_draw_frame(&engine);
}

}

效果如图所示。

APK下载:下载

时间: 2024-10-13 05:12:26

Android-NDK处理用户交互事件的相关文章

Cocos2d-x 系列七之用户交互

如同android中的用户交互,cocos2d-x通常也需要对一些用户点击.触摸事件进行监听: 一. 简单触摸事件 auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesBegan = [](const std::vector<Touch*>&, Event*) { log("onTouchesBegan"); }; listener->onTouchesMov

Android SDK上手指南 3:用户交互

在这篇教程中,我们将对之前所添加的Button元素进行设置以实现对用户点击的检测与响应.为了达成这一目标,我们需要在应用程序的主Activity类中略微涉及Java编程内容.如果大家在Java开发方面的经验不太丰富也没必要担心,只要按步骤进行即可完成学习.我们将在本系列的下一篇文章中深入探讨Java语法,从而保证大家了解初步Android开发任务中所必需的编程语言知识. 大家可以在Android当中以多种不同方式实现用户交互.我们将学习两种最为典型的处理方案,从而实现应用按钮对用户点击的感应--

控件不接收用户交互的情况以及事件响应顺序

开发中经常会遇到控件不接收用户交互了,可以从以下几个方面检查: 1. enable = NO 就不可以被点击 ->也会让按钮显示禁用状态 2. 设置了控件的 userInterActionEnabel = NO 3. hidden属性为YES 4. 控件的alpha < = 0.01 5. 如果一个父控件与用户的交互设置为NO ,那么它子控件将获取不到交互事件 6.如果子视图超出父视图范围,超出范围的部分也不能接收用户交互 7. 触发事件的过程 1). 交互事件,是先由父控件获取到,然后父控件

Android NDK开发(八)——应用监听自身卸载,弹出用户反馈调查

转载请注明出处:http://blog.csdn.net/allen315410/article/details/42521251 监听卸载情景和原理分析 1,情景分析 在上上篇博客中我写了一下NDK开发实践项目,使用开源的LAME库转码MP3,作为前面几篇基础博客的加深理解使用的,但是这样的项目用处不大,除了练练NDK功底.这篇博客,我将讲述一下一个各大应用中很常见的一个功能,同样也是基于JNI开发的Android应用小Demo,看完这个之后,不仅可以加深对NDK开发的理解,而且该Demo也可

通过Android studio编写用户注册信息表单(实现用户交互)小demo

通过Android studio编写用户注册信息表单(实现用户交互)小demo,话不多说直接上小demo 1.activity_ main.xml中的约束布局设计原型样式图:  2.在模拟器中演示效果:  3.实现约束布局代码,代码存放在activity_ main.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayou

10天学通Android开发(4)-用户布局与常用控件

常用布局 FrameLayout:子元素没有相对位置概念,都相对于左上角 LinearLayout:线性布局,一个接一个,水平或垂直 RelativeLayout:相对布局,可相对其它子元素 TableLayout:水平和垂直LinearLayout的混和 如: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.andr

android知识回顾--view的事件体系

1.view的滑动,六种滑动方式:    一:通过layout来实现滑动效果      package com.example.testdragview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; public class DragView

高德地图组件在Android的应用以及Android与JavaScript的交互

最近在慕课网学习了关于高德地图组件的课程(其实就是一个广告,内容和官网的API完全一样),发现这个JavaScript API比Android API简单方便多了,于是就打算放在Android APP上来实现,花了一点小功夫,但是最终还是实现了,后来打算扩展的时候遇到个问题:就是高德官网有一个坐标拾取点(高德的坐标和我们平时取的坐标不一样,可以将高德坐标理解为中国的国标,直接获取的坐标是国际标准的坐标),后来发现有html文件直接实现了这个功能,于是就把这个html扒出来了,但是重点问题来了:如

如何定位Android NDK开发中遇到的错误

做android应用的调试,最怕就是报错,crash,看到这篇好文章,记录一下: 转自:http://www.csdn.net/article/2014-12-30/2823366-Locate-Android-NDK Android NDK是什么? Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Kit,因此又被Google称为“NDK”.众所周知,Android程序运行在Dalvik虚拟机中,NDK允许用户使用类似C / C++之类的原生代