找遍了全网,没有一个完整的可用的框架。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 */