您的位置:首页 > 其它

NativeActivity原理

2015-07-07 14:18 330 查看
在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); //创建一个线程通信的对象。用于主线程(UI线程)和我们的线程通信。

//检查看看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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: