android_app c++框架

找遍了全网,没有一个完整的可用的框架。ndk自带的android_native_app_glue确实不太好用,闭关几天,写出了一个框架。完全的消息队列调用,目前测试的主体框架是没有什么问题了,程序入口还是android_main。调用过程:

void android_main(android_app* app)
{
  //APP_LOG("main : 程序启动");
  //设置消息回调函数,就一个,整体和win32编程差不多了。
  app->onEvent = on_app_event;

  //循环等待事情以进行处理。
  while (app->running){//app处于运行状态
    app->process_message();//处理消息主函数
    if(!app->pause()){
      //draw_frame();//绘制我们的游戏,相当于MainLoop事件
    }
    else{
      //APP_LOG("PAUSE");
    }
  }
  //APP_LOG("main : 程序结束");
}

   

消息事件结构:

#pragma pack(push, 1)
struct APP_EVENT
{
    int id;
    union{
        void* data;
        struct{//input motion
            int16_t x, y, z, w;
        };
        struct{//input_keyboard
            int32_t key;
            int32_t flag;
        };
        struct{//ARect
            int16_t left, top, right, bottom;
        };
    };
};
#pragma pack(pop)

  

主消息处理函数,完全防win32编程设计,当然,事件处理做的还不够全面。现在只是初期框架,但这个框架已经比glue那个清晰多了。

主消息回调函数: 

void on_app_event(android_app* app, APP_EVENT& event)
{
	switch(event.id)
	{
	case APP_START://activity启动
		break;
	case APP_STOP://停止
		break;
	case APP_RESUME://返回
		break;
	case APP_PAUSE://暂停
		break;
	case APP_DESTROY://销毁退出
		break;
	case APP_SAVE://保存状态
		break;
	case APP_WINDOW_CREATE://窗口创建,app->window有效
		break;
	case APP_WINDOW_CLOSE://窗口销毁
		break;
	case APP_WINDOW_ACTIVATE://窗口获得焦点
		break;
	case APP_WINDOW_DEACTIVATE://窗口失去焦点
		break;
	case APP_WINDOW_RESIZE://窗口大小改变
		break;

	case APP_TOUCH_DOWN://触摸按下
		//这三个事件,都使用event.x, event.y作为坐标
		//event.z代表pointerid
		break;
	case APP_TOUCH_MOVE://触摸滑动
		break;
	case APP_TOUCH_UP:
		break;

	default:
		//APP_LOG("unknow msg:%d", cmd);
		break;
	}
} 

   

ndk的activity入口函数其实是:

void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize);

这个函数由主进程调用,主进程创建一个activity,通知native库创建环境并处理,如果这个函数不返回,app就会卡死无响应。所以我们native库的过程要在一个新的线程里面处理。直接使用主线程的回调也不是不可以,但无法处理MainLoop这个事件,这个事件主线程没给。如果新建一个线程,如何处理主线程回调的事件,就是一个根本的问题。glue库用了pipe,并大把大把的mutex lock处理。下面这个库,把lock基本都去掉了,不再使用ALooper进行消息处理。主线程和线程之间的通信还是用的pipe,因为简单易用。

方式很简单:(执行标准)

一:所有ANativeActivity_onCreate里面指定的回调函数,执行过程都在主线程里面,这个我们要打包。用APP_EVENT把事件封装,通过pipe发送到我们线程的事件队列,不对android_app内部数据进行操作。

二:android_main()过程里面,循环执行process_message(),进行事件处理。process_message()的执行过程就是,从pipe里面读取打包的APP_EVENT,并进行预处理、回调执行、后续处理。

三:所有事件方法,过程尽量保证清晰,可读性高。

 

目前库封装了部分输入交互操作,后续会继续封装。也欢迎大家评论,有用的着的尽可拿去用,public domain协议!

 

 

  1 #ifndef ANDROID_APP_HPP
  2 #define ANDROID_APP_HPP
  3 
  4 #include <errno.h>
  5 #include <fcntl.h>
  6 #include <poll.h>
  7 #include <pthread.h>
  8 #include <sched.h>
  9 #include <stdlib.h>
 10 #include <string.h>
 11 #include <unistd.h>
 12 #include <sys/resource.h>
 13 
 14 #include<sys/ioctl.h>
 15 
 16 #include <jni.h>
 17 
 18 #include <android/configuration.h>
 19 #include <android/looper.h>
 20 #include <android/native_activity.h>
 21 #include <android/log.h>
 22 
 23 #include "pipefile.hpp"//封装的pipe操作,之后会发表
 24 
 25 #include <cgl/public.h>//#define null NULL
 26 #include <cgl/thread/mutex.hpp>//封装的锁操作,之后发表
 27 
 28 using namespace cgl;
 29 
 30 #define ANDROID_APP_LOG(...) ((void)__android_log_print(ANDROID_LOG_INFO, "android_app", __VA_ARGS__))
 31 #define ANDROID_APP_ERROR(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "android_app", __VA_ARGS__))
 32 
 33 #define ANDROID_APP_DEBUG//debug 模式
 34 
 35 #ifdef ANDROID_APP_DEBUG
 36 #define ANDROID_APP_LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "android_app", __VA_ARGS__))
 37 #else
 38 #define ANDROID_APP_LOGV(...) ((void)0)
 39 #endif
 40 
 41 //android app events
 42 enum ANDROID_APP_EVENT
 43 {
 44     APP_START,
 45     APP_STOP,
 46     APP_RESUME,
 47     APP_PAUSE,
 48     APP_DESTROY,
 49     APP_SAVE,
 50     APP_CONFIG,
 51     APP_LOW_MEMORY,
 52 
 53     APP_WINDOW_CREATE,    //set app.window
 54     APP_WINDOW_CLOSE,    //reset app.window
 55     APP_WINDOW_ACTIVATE,
 56     APP_WINDOW_DEACTIVATE,
 57     APP_WINDOW_RESIZE,
 58     APP_WINDOW_RECT_CHANGED,
 59     APP_WINDOW_PAINT,
 60 
 61     APP_INPUT,        //set app.inputQueue
 62     APP_TOUCH_DOWN,
 63     APP_TOUCH_UP,
 64     APP_TOUCH_MOVE,
 65 
 66     APP_KEY_UP,
 67     APP_KEY_DOWN,
 68     APP_KEY_PRESS
 69 };
 70 
 71 #pragma pack(push, 1)
 72 struct APP_EVENT
 73 {
 74     int id;
 75     union{
 76         void* data;
 77         struct{//input motion
 78             int16_t x, y, z, w;
 79         };
 80         struct{//input_keyboard
 81             int32_t key;
 82             int32_t flag;
 83         };
 84         struct{//ARect
 85             int16_t left, top, right, bottom;
 86         };
 87     };
 88 };
 89 #pragma pack(pop)
 90 
 91 class android_app;
 92 
 93 extern void android_main(android_app* app);
 94 
 95 void android_app_post_event(android_app* app, const APP_EVENT& event);
 96 void android_app_post_event(android_app* app, int id);
 97 
 98 class android_app
 99 {
100 public:
101     ANativeActivity* activity;
102     AConfiguration* config;
103     ALooper* looper;
104     ANativeWindow* window;
105 
106     void* savedState;
107     size_t savedStateSize;
108     int stateSaved;
109 
110     void* userData;
111 
112     void (*onEvent)(android_app* app, APP_EVENT& event);
113 
114     int activityState;
115     bool running;
116 public:
117     pthread_t thread;
118     mutex_t mutex;
119     cond_t  cond;
120 public:
121     io::pipefile message;
122     AInputQueue* inputQueue;
123     int destroyed;
124 public:
125     android_app() : activity(null), config(null), looper(null), window(null),
126         savedState(null), savedStateSize(0), stateSaved(0),
127         userData(null),
128         onEvent(null),
129         activityState(0),
130         thread(), mutex(), cond(),
131         message(),
132         inputQueue(null),
133         destroyed(0)
134     {
135         running = false;
136     }
137 
138     void dispose();
139 
140     bool pause()const
141     {
142         return activityState == APP_PAUSE;// || activityState == APP_STOP;
143     }
144 
145     int process_message()
146     {
147         APP_EVENT event;
148         int bytes;
149         ioctl(message.in(), FIONREAD, &bytes);
150         while(bytes){
151             if(this->read_event(event)){
152                 //ANDROID_APP_LOGV("process message %d - %p", event.id, event.data);
153                 this->process_begin(event);
154                 if(this->onEvent){
155                     this->onEvent(this, event);
156                 }
157                 this->process_end(event);
158             }
159             ioctl(message.in(), FIONREAD, &bytes);
160         }
161         ALooper_pollAll(0, NULL, NULL, NULL);
162         //如果传感器有数据,立即处理。ident == USER
163         //ANDROID_APP_LOG("pollAll %d", ident);
164         return 0;
165     }
166 
167 public://log
168     void print_config();
169 public:
170     void cond_wait()
171     {
172         cond.wait(mutex);
173     }
174 
175 public:
176     static int on_input(int fd, int events, void* data);
177     int on_input_event(AInputEvent* event);
178 private:
179     bool read_event(APP_EVENT& event);
180     void process_begin(APP_EVENT& event);
181     void process_end(APP_EVENT& event);
182 
183     int on_input_motion(AInputEvent* event);
184     int on_input_keyboard(AInputEvent* event);
185 };
186 
187 void free_saved_state(android_app* app)
188 {
189     //auto_lock lock(app->mutex);
190     if (app->savedState != NULL) {
191         free(app->savedState);
192         app->savedState = NULL;
193         app->savedStateSize = 0;
194     }
195 }
196 
197 void android_app::print_config()
198 {
199     char lang[2], country[2];
200     AConfiguration_getLanguage(config, lang);
201     AConfiguration_getCountry(config, country);
202 
203     ANDROID_APP_LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
204             "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
205             "modetype=%d modenight=%d",
206             AConfiguration_getMcc(config),
207             AConfiguration_getMnc(config),
208             lang[0], lang[1], country[0], country[1],
209             AConfiguration_getOrientation(config),
210             AConfiguration_getTouchscreen(config),
211             AConfiguration_getDensity(config),
212             AConfiguration_getKeyboard(config),
213             AConfiguration_getNavigation(config),
214             AConfiguration_getKeysHidden(config),
215             AConfiguration_getNavHidden(config),
216             AConfiguration_getSdkVersion(config),
217             AConfiguration_getScreenSize(config),
218             AConfiguration_getScreenLong(config),
219             AConfiguration_getUiModeType(config),
220             AConfiguration_getUiModeNight(config));
221 }
222 
223 #ifdef ANDROID_APP_DEBUG
224 const char* input_motion_name(int action)
225 {
226     switch(action){
227     case AMOTION_EVENT_ACTION_DOWN://触摸按下
228         return "MOTION_DOWN";
229     case AMOTION_EVENT_ACTION_UP://触摸弹起
230         return "MOTION_UP";
231     case AMOTION_EVENT_ACTION_MOVE://触摸移动
232         return "MOTION_MOVE";
233     case AMOTION_EVENT_ACTION_CANCEL:
234         return "MOTION_CACEL";
235     case AMOTION_EVENT_ACTION_OUTSIDE:
236         return "MOTION_OUTSIDE";
237     default:
238         break;
239     }
240     return null;
241 }
242 #endif
243 
244 int android_app::on_input_motion(AInputEvent* inputEvent)
245 {
246     APP_EVENT event;
247 
248     //motion source
249     switch(AInputEvent_getSource(inputEvent))
250     {
251     case AINPUT_SOURCE_TOUCHSCREEN:
252         //消息来源于触摸屏
253         break;
254     case AINPUT_SOURCE_TRACKBALL:
255         //消息来源于trackball,轨迹球 or 鼠标?
256         break;
257     default:
258         break;
259     }
260 
261     switch(AMotionEvent_getAction(inputEvent))
262     {
263     case AMOTION_EVENT_ACTION_DOWN://触摸按下
264         event.id = APP_TOUCH_DOWN;
265         break;
266     case AMOTION_EVENT_ACTION_UP://触摸弹起
267         event.id = APP_TOUCH_UP;
268         break;
269     case AMOTION_EVENT_ACTION_MOVE://触摸移动
270         event.id = APP_TOUCH_MOVE;
271         break;
272     case AMOTION_EVENT_ACTION_CANCEL:
273         break;
274     case AMOTION_EVENT_ACTION_OUTSIDE:
275         break;
276     default:
277         break;
278     }
279 
280     //getX()    是表示view相对于自身左上角的x坐标,
281     //getRawX()    是表示相对于物理屏幕左上角的x坐标值
282     //AMotionEvent_getXPrecision
283 
284     size_t count = AMotionEvent_getPointerCount(inputEvent);
285     for(int i=0; i < count; ++i){
286         event.x = AMotionEvent_getX(inputEvent, i);
287         event.y = AMotionEvent_getY(inputEvent, i);
288         event.z = i;
289 
290         if(this->onEvent){
291             this->onEvent(this, event);
292         }
293 
294         #ifdef ANDROID_APP_DEBUG
295         ANDROID_APP_LOGV("%s : index=%d, pointer=%d, flag=%d state=%d x=%d, y=%d\n", 
296             input_motion_name(AMotionEvent_getAction(inputEvent)),
297             i,
298             AMotionEvent_getPointerId(inputEvent, i),
299             AMotionEvent_getFlags(inputEvent), 
300             AMotionEvent_getMetaState(inputEvent),
301             event.x, event.y);
302         #endif
303     }
304     return this->onEvent ? 1 : 0;
305 }
306 
307 int android_app::on_input_keyboard(AInputEvent* inputEvent)
308 {
309     //键盘控制键管用,字符键不管用
310     ANDROID_APP_LOGV("keyinput : action=%d flag=%d keycode=%d",
311         AKeyEvent_getAction(inputEvent),
312         AKeyEvent_getFlags(inputEvent),
313         AKeyEvent_getKeyCode(inputEvent));
314 
315     APP_EVENT event;
316     switch(AKeyEvent_getAction(inputEvent)){
317     case AKEY_STATE_UNKNOWN:
318         break;
319     case AKEY_STATE_UP:
320         event.id = APP_KEY_UP;
321         break;
322     case AKEY_STATE_DOWN:
323         event.id = APP_KEY_DOWN;
324         break;
325     case AKEY_STATE_VIRTUAL:
326         event.id = APP_KEY_PRESS;
327         break;
328     default:
329         break;
330     }
331 
332     event.key = AKeyEvent_getKeyCode(inputEvent);
333     event.flag = AKeyEvent_getFlags(inputEvent);
334     if(this->onEvent){//if processed, reutrn 1
335         this->onEvent(this, event);
336         return 1;
337     }
338 
339     return 0;
340 }
341 
342 // input event callback
343 int android_app::on_input_event(AInputEvent* inputEvent)
344 {
345     if(AInputEvent_getType(inputEvent) == AINPUT_EVENT_TYPE_MOTION){
346         return this->on_input_motion(inputEvent);
347     }
348     else if(AInputEvent_getType(inputEvent) == AINPUT_EVENT_TYPE_KEY){
349         return this->on_input_keyboard(inputEvent);        
350     }
351     return 0;
352 }
353 
354 // inputQueue callback
355 int android_app::on_input(int fd, int events, void* data)
356 {
357     ANDROID_APP_LOGV("on_input %p", data);
358     android_app* app = (android_app*)data;
359     AInputEvent* event = NULL;
360     while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
361         //ANDROID_APP_LOGV("New input event: type=%d\n", AInputEvent_getType(event));
362         if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
363             continue;
364         }
365         AInputQueue_finishEvent(app->inputQueue, event, app->on_input_event(event));
366     }
367     return 1;
368 }
369 
370 //读取事件
371 bool android_app::read_event(APP_EVENT& event)
372 {
373     return message.read(&event, sizeof(event)) == sizeof(event);
374 }
375 
376 #ifdef ANDROID_APP_DEBUG
377 const char* app_event_name(int id)
378 {
379     switch (id)
380     {
381         case APP_START:                return "APP_START";
382         case APP_STOP:                return "APP_STOP";
383         case APP_RESUME:            return "APP_RESUME";
384         case APP_PAUSE:                return "APP_PAUSE";
385         case APP_DESTROY:            return "APP_DESTROY";
386         case APP_SAVE:                return "APP_SAVE";
387         case APP_CONFIG:            return "APP_CONFIG";
388         case APP_WINDOW_CREATE:        return "APP_WINDOW_CREATE";
389         case APP_WINDOW_CLOSE:        return "APP_WINDOW_CLOSE";
390         case APP_WINDOW_ACTIVATE:    return "APP_WINDOW_ACTIVATE";
391         case APP_WINDOW_DEACTIVATE: return "APP_WINDOW_DEACTIVATE";
392         case APP_WINDOW_RESIZE:        return "APP_WINDOW_RESIZE";
393         case APP_INPUT:                return "APP_INPUT";
394         default:
395             break;
396     }
397     return null;
398 }
399 #endif
400 
401 //预处理事件
402 void android_app::process_begin(APP_EVENT& event)
403 {
404     switch (event.id){
405     case APP_START:
406     case APP_STOP:
407     case APP_RESUME:
408     case APP_PAUSE:
409         ANDROID_APP_LOGV("APP_STATE = %s\n", app_event_name(event.id));
410         this->activityState = event.id;
411         break;
412     case APP_DESTROY:
413         ANDROID_APP_LOGV("APP_DESTROY\n");
414         this->running = false;
415         break;
416     case APP_SAVE:
417         //free_saved_state(this);
418         break;
419     case APP_CONFIG:
420         ANDROID_APP_LOGV("APP_CONFIG\n");
421         AConfiguration_fromAssetManager(this->config, this->activity->assetManager);
422         this->print_config();
423         break;
424 
425     case APP_WINDOW_CREATE:
426         ANDROID_APP_LOGV("APP_WINDOW_CREATE : %p\n", event.data);
427         this->window = (ANativeWindow*)event.data;
428         break;
429     case APP_INPUT:{
430         ANDROID_APP_LOGV("APP_INPUT : %p\n", event.data);
431         if(this->inputQueue){
432             AInputQueue_detachLooper(this->inputQueue);
433         }
434         this->inputQueue = (AInputQueue*)event.data;
435         if(this->inputQueue){
436             AInputQueue_attachLooper(this->inputQueue, this->looper, 0, android_app::on_input, this);
437         }
438         break;
439     }
440     default:
441         ANDROID_APP_LOGV("APP_EVENT : %s", app_event_name(event.id));
442         break;
443     }
444 }
445 
446 //后续处理事件
447 void android_app::process_end(APP_EVENT& event)
448 {
449     switch (event.id) {
450     case APP_WINDOW_CLOSE:
451         ANDROID_APP_LOGV("APP_WINDOW_CLOSE\n");
452         this->window = NULL;
453         break;
454     case APP_SAVE:
455         ANDROID_APP_LOGV("APP_SAVE\n");
456         this->stateSaved = 1;
457         break;
458     case APP_RESUME:
459         //free_saved_state(this);
460         break;
461     default:
462         break;
463     }
464 }
465 
466 void android_app::dispose()
467 {
468     ANDROID_APP_LOGV("android_app::dispose!");
469     free_saved_state(this);
470     //auto_lock lock(app->mutex);
471     if(this->inputQueue){
472         AInputQueue_detachLooper(this->inputQueue);
473     }
474     AConfiguration_delete(this->config);
475     this->destroyed = 1;
476     this->cond.broadcast();
477     // Can‘t touch android_app object after this.
478 }
479 
480 // app main thread
481 void* android_app_main(void* param)
482 {
483     android_app* app = (android_app*)param;
484 
485     app->config = AConfiguration_new();
486     AConfiguration_fromAssetManager(app->config, app->activity->assetManager);
487     app->print_config();
488 
489     app->looper = ALooper_prepare(0);
490     app->running = true;
491 
492     android_main(app);    //android_main
493 
494     app->dispose();
495 
496     return NULL;
497 }
498 
499 // --------------------------------------------------------------------
500 //
501 // Native activity interaction (主线程调用的函数)
502 //
503 // --------------------------------------------------------------------
504 
505 android_app* android_app_create(ANativeActivity* activity, void* savedState, size_t savedStateSize)
506 {
507     android_app* app = new android_app;
508     app->activity = activity;
509 
510     if (savedState != NULL) {
511         /*
512         app->savedState = malloc(savedStateSize);
513         app->savedStateSize = savedStateSize;
514         memcpy(app->savedState, savedState, savedStateSize);
515         */
516     }
517 
518     if(app->message.create()){
519         ANDROID_APP_ERROR("could not create pipe: %s", strerror(errno));
520         return NULL;
521     }
522 
523     //int flag = fcntl(app->message.in(), F_GETFL, 0 );
524     //fcntl(app->message.in(), F_SETFL, flag | O_NONBLOCK);
525 
526     pthread_attr_t attr;
527     pthread_attr_init(&attr);
528     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
529     pthread_create(&app->thread, &attr, android_app_main, app);
530 
531     return app;
532 }
533 
534 void android_app_post_event(android_app* app, const APP_EVENT& event)
535 {
536     //ANDROID_APP_LOGV("write event %d", event.id);
537     if(app->message.write(&event, sizeof(event)) != sizeof(event)) {
538         ANDROID_APP_ERROR("Failure writing android_app event: %s\n", strerror(errno));
539     }
540 }
541 
542 void android_app_post_event(android_app* app, int id)
543 {
544     APP_EVENT event = {id};
545     android_app_post_event(app, event);
546 }
547 
548 //
549 // 主线程回调函数
550 //
551 
552 //
553 // app
554 //
555 
556 void onStart(ANativeActivity* activity)
557 {
558     ANDROID_APP_LOGV("Activity Start: %p\n", activity);
559     android_app_post_event((android_app*)activity->instance, APP_START);
560 }
561 
562 void onStop(ANativeActivity* activity)
563 {
564     ANDROID_APP_LOGV("Activity Stop: %p\n", activity);
565     android_app_post_event((android_app*)activity->instance, APP_STOP);
566 }
567 
568 void onResume(ANativeActivity* activity)
569 {
570     ANDROID_APP_LOGV("Activity Resume: %p\n", activity);
571     android_app_post_event((android_app*)activity->instance, APP_RESUME);
572 }
573 
574 void onPause(ANativeActivity* activity)
575 {
576     ANDROID_APP_LOGV("Activity Pause: %p\n", activity);
577     android_app_post_event((android_app*)activity->instance, APP_PAUSE);
578 }
579 
580 void onDestroy(ANativeActivity* activity)
581 {
582     ANDROID_APP_LOGV("Activity Destroy: %p\n", activity);
583     android_app* app = (android_app*)activity->instance;
584     //auto_lock lock(app->mutex);
585     android_app_post_event(app, APP_DESTROY);
586     while (!app->destroyed) {
587         //app->cond_wait();
588     }
589 
590     app->message.close();
591     delete app;
592 }
593 
594 void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
595 {
596     android_app* app = (android_app*)activity->instance;
597     void* savedState = NULL;
598 
599     ANDROID_APP_LOGV("Activity SaveInstanceState: %p\n", activity);
600     /*
601     auto_lock lock(app->mutex);
602     app->stateSaved = 0;
603     android_app_post_event(app, APP_SAVE);
604     while (!app->stateSaved) {
605         app->cond_wait();
606     }
607 
608     if (app->savedState != NULL) {
609         savedState = app->savedState;
610         *outLen = app->savedStateSize;
611         app->savedState = NULL;
612         app->savedStateSize = 0;
613     }
614     */
615     return savedState;
616 }
617 
618 void onConfigurationChanged(ANativeActivity* activity) {
619     ANDROID_APP_LOGV("Activity ConfigurationChanged: %p\n", activity);
620     android_app_post_event((android_app*)activity->instance, APP_CONFIG);
621 }
622 
623 void onLowMemory(ANativeActivity* activity)
624 {
625     ANDROID_APP_LOGV("Activity LowMemory: %p\n", activity);
626     android_app_post_event((android_app*)activity->instance, APP_LOW_MEMORY);
627 }
628 
629 //
630 // window
631 //
632 
633 void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window)
634 {
635     ANDROID_APP_LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
636     APP_EVENT event;
637     event.id = APP_WINDOW_CREATE;
638     event.data = window;
639     android_app_post_event((android_app*)activity->instance, event);
640 }
641 
642 void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window)
643 {
644     ANDROID_APP_LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
645     android_app_post_event((android_app*)activity->instance, APP_WINDOW_CLOSE);
646 }
647 
648 void onWindowFocusChanged(ANativeActivity* activity, int focused)
649 {
650     ANDROID_APP_LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
651     android_app_post_event((android_app*)activity->instance, focused ? APP_WINDOW_ACTIVATE : APP_WINDOW_DEACTIVATE);
652 }
653 
654 void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window)
655 {
656     ANDROID_APP_LOGV("NativeWindowResized: %p -- %p\n", activity, window);
657     android_app_post_event((android_app*)activity->instance, APP_WINDOW_RESIZE);
658 }
659 
660 void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
661 {
662     ANDROID_APP_LOGV("ContentRectChanged: [%d, %d - %d, %d]\n", rect->left, rect->top, rect->right, rect->bottom);
663     /*
664     APP_EVENT event;
665     event.id     = APP_WINDOW_RECT_CHANGED;
666     event.left   = rect->left;
667     event.top    = rect->top;
668     event.right  = rect->right;
669     event.bottom = rect->bottom;
670     android_app_post_event((android_app*)activity->instance, event);
671     */
672 }
673 
674 void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window)
675 {
676     ANDROID_APP_LOGV("NativeWindowRedrawNeeded: %p -- %p\n", activity, window);
677     android_app_post_event((android_app*)activity->instance, APP_WINDOW_PAINT);
678 }
679 
680 //
681 // input
682 //
683 
684 void android_app_set_input(android_app* app, AInputQueue* inputQueue)
685 {
686     APP_EVENT event;
687     event.id = APP_INPUT;
688     event.data = inputQueue;
689     android_app_post_event(app, event);
690 }
691 
692 void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
693 {
694     ANDROID_APP_LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
695     android_app_set_input((android_app*)activity->instance, queue);
696 }
697 
698 void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
699 {
700     ANDROID_APP_LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
701     android_app_set_input((android_app*)activity->instance, NULL);
702 }
703 
704 //
705 // native activity entry
706 //
707 
708 JNIEXPORT
709 void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
710 {
711     ANDROID_APP_LOGV("NativeActivity create: %p\n", activity);
712 
713     //app
714     activity->callbacks->onStart   = onStart;
715     activity->callbacks->onStop    = onStop;
716     activity->callbacks->onResume  = onResume;
717     activity->callbacks->onPause   = onPause;
718     activity->callbacks->onDestroy = onDestroy;
719     activity->callbacks->onSaveInstanceState    = onSaveInstanceState;
720     activity->callbacks->onConfigurationChanged = onConfigurationChanged;
721     activity->callbacks->onLowMemory = onLowMemory;
722 
723     //window
724     activity->callbacks->onNativeWindowCreated      = onNativeWindowCreated;
725     activity->callbacks->onNativeWindowDestroyed    = onNativeWindowDestroyed;
726     activity->callbacks->onWindowFocusChanged       = onWindowFocusChanged;
727     activity->callbacks->onNativeWindowResized      = onNativeWindowResized;
728     activity->callbacks->onContentRectChanged       = onContentRectChanged;
729     activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
730 
731     //input
732     activity->callbacks->onInputQueueCreated   = onInputQueueCreated;
733     activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
734 
735     //create android app
736     activity->instance = android_app_create(activity, savedState, savedStateSize);
737 
738     //ANDROID_APP_LOGV("NativeActivity create successed.");
739 }
740 
741 #endif /* ANDROID_APP_HPP  */

 

android_app c++框架

上一篇:Android应用开发中三种常见的图片压缩方法


下一篇:封装一个Automapper单例