NativeActivity原理

写android纯c++的程序需要用到NativeActivity,这个NativeActivity就是一个一般的java类,和普通的activity没有区别。

NativeActivity 是android sdk自带的一个activity。android的纯c++的程序也是需要一个java虚拟机来运行的。nativeActivity通过native_app_glu来启动我们的c++线程,传递各种activity事件给我的c++代码。native_app_glu在ndk的sources\android目录里面,将native_app_glu当做我们工程的静态库,这个静态库里面封装好了,会创建一个线程,这个线程里面会调用一个android_main(android_app* pApplication)的函数,因此,我们c++这边的入口函数就是android_main()我们在这个android_main()函数里面的任务就是进行消息循环,做各种任务。

在AndroidManifest.xml文件里面指定入口activity为nativeactivity,

这样应用程序一启动,java虚拟机这边就开一个主线程,主线程创建一个活动,就是nativeactivity,

这个nativeactivity在创建的过程中就会去应用程序的.so动态链接库中寻找一个函数:__ANativeActivity_onCreate(ANativeActivity, void* size_t),然后调用这个函数,这个函数就是C++代码中的真正的入口函数,在这个入口函数里面

做写什么事情呢,请参考ndk里面的Native_app_glue。它是这样来实现的:

对这个传进来的ANativeActivity, 设置这个activity的各种是事件的回调函数:

activity->callbacks->onDestroy = onDestroy;

activity->callbacks->onStart = onStart;

设置完了之后就调用:

activity->instance = android_app_create(activity, savedState, savedStateSize);

过程就这么简单,完了,现在分析下android_app_create这个函数:

 static struct android_app* android_app_create(ANativeActivity* activity,
         void* savedState, size_t savedStateSize) {



//首先创建一个android_app结构体,这个结构体参见android_native_app_glue.h
     struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
     memset(android_app, 0, sizeof(struct android_app));


     android_app->activity = activity;
 //设置app的activity


     pthread_mutex_init(&android_app->mutex, NULL);
  //创建一个线程同步对象 mutex互斥体,
     pthread_cond_init(&android_app->cond, NULL);
  //创建一个条件变量。用于线程同步



//检查看看android系统之前是否已经为我们的应用程序保存过状态。有的话直接恢复就好了。

//还有比较重要的一条信息,android应用程序的屏幕方向变化的话,activity也要从新建立!!!!!
     if (savedState != NULL) {
         android_app->savedState = malloc(savedStateSize);
         android_app->savedStateSize = savedStateSize;
         memcpy(android_app->savedState, savedState, savedStateSize);
     }





//创建两个管道对象,用于线程读写消息时同步。
     int msgpipe[2];
     if (pipe(msgpipe)) {
         LOGE("could not create pipe: %s", strerror(errno));
         return NULL;
     }
     android_app->msgread = msgpipe[0];
     android_app->msgwrite = msgpipe[1];



//创建我们的线程,我们的代码就是运行在这个线程里面的,
     pthread_attr_t attr; 
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

//这里指定了线程入口函数,和一个userdata数据就是android_app这个结构体。
     pthread_create(&android_app->thread, &attr, android_app_entry, android_app);


     //等待我们的线程启动.
     pthread_mutex_lock(&android_app->mutex);



//等待我们的线程启动,
     while (!android_app->running) {
         pthread_cond_wait(&android_app->cond, &android_app->mutex);
     }
     pthread_mutex_unlock(&android_app->mutex);



//我们的线程启动完了之后,返回这个结构体。这样activity的oncreate就完成了。

//主线程中剩下的代码就在做各种事件消息的路由。
     return android_app;
 }

现在来看看我们的线程的入口函数:android_app_entry, 

 static void* android_app_entry(void* param) {

//param是上面的函数创建线程的时候传进来的。
     struct android_app* android_app = (struct android_app*)param;



//创建应用程序config
     android_app->config = AConfiguration_new();
     AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);



//通过log打印应用的config
     print_cur_config(android_app);



//从主线程抓取消息用的
     android_app->cmdPollSource.id = LOOPER_ID_MAIN;
     android_app->cmdPollSource.app = android_app;
     android_app->cmdPollSource.process = process_cmd;
//设置处理cmd的一个函数。
     android_app->inputPollSource.id = LOOPER_ID_INPUT;
     android_app->inputPollSource.app = android_app;
     android_app->inputPollSource.process = process_input;//输入事件处理函数,



//创建一个looper消息循环,抓取消息。
     ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
     ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
             &android_app->cmdPollSource);
     android_app->looper = looper;


     pthread_mutex_lock(&android_app->mutex);
     android_app->running = 1;
 //这里这么设置activity的oncreate函数就会退出。
     pthread_cond_broadcast(&android_app->cond);
     pthread_mutex_unlock(&android_app->mutex);


     android_main(android_app);
 //调用我们的代码的入口函数。在我们自己实现的的这个入口函数里面

//在消息循环里面不断的抓取消息处理,或做其他事情,直到控制退出,然后

//这个线程才会结束。


     android_app_destroy(android_app);
 //销毁android_app退出线程。
     return NULL;
 }

处理cmd的函数:

static void process_cmd(struct android_app* app, struct android_poll_source* source) {
     int8_t cmd = android_app_read_cmd(app);
     android_app_pre_exec_cmd(app, cmd);
     if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
     android_app_post_exec_cmd(app, cmd);
 }
处理输入的函数
 static void process_input(struct android_app* app, struct android_poll_source* source) {
     AInputEvent* event = NULL;
     if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
         LOGV("New input event: type=%d\n", AInputEvent_getType(event));
         if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
             return;
         }
         int32_t handled = 0;
         if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);//这里交给android_app的onInputEvent

//去处理,也就是我们自己写的输入处理函数。
         AInputQueue_finishEvent(app->inputQueue, event, handled);
     } else {
         LOGE("Failure reading next input event: %s\n", strerror(errno));
     }
 }

typedef struct ANativeActivity {
     /**
      * 指向一个拥有各种事件回调函数的结构体指针,onStart,onResume,onPause,onStop,onDestroy
      */
     struct ANativeActivityCallbacks* callbacks;
     /**
      * The global handle on the process's Java VM.
      */
     JavaVM* vm;
     /**
      * JNI context for the main thread of the app.  Note that this field
      * can ONLY be used from the main thread of the process; that is, the
      * thread that calls into the ANativeActivityCallbacks.


     */
     JNIEnv* env;
     /**
      * The NativeActivity object handle.
      *
      * IMPORTANT NOTE: This member is mis-named. It should really be named
      * 'activity' instead of 'clazz', since it's a reference to the
      * NativeActivity instance created by the system for you.
      *
      * We unfortunately cannot change this without breaking NDK
      * source-compatibility.
      */
     jobject clazz;
     /**
      * Path to this application's internal data directory.
      */
     const char* internalDataPath;
     
     /**
      * Path to this application's external (removable/mountable) data directory.
      */
     const char* externalDataPath;
     
     /**
      * The platform's SDK version code.
      */
     int32_t sdkVersion;
     
     /**
      * This is the native instance of the application.  It is not used by
      * the framework, but can be set by the application to its own instance
      * state.
      */
     void* instance;
 //这个用于指向android_app了。
     /**
      * Pointer to the Asset Manager instance for the application.  The application
      * uses this to access binary assets bundled inside its own .apk file.
      */
     AAssetManager* assetManager;
 } ANativeActivity;

原文链接: https://blog.csdn.net/ldpxxx/article/details/9253369