NativeActivity原理

来源:互联网 发布:网络小贷牌照申请条件 编辑:程序博客网 时间:2024/05/17 09:10
在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;
0 0
原创粉丝点击