NativeActivity原理

转载 2015年07月07日 14:18:00
在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;
举报

相关文章推荐

NativeActivity的胶水层android_native_app_glue详解和使用

使用NativeActivity可以完全不使用java代码,全部使用native code来开发android程序。NativeActivity 为我们定制了native代码的各种接口回调,在ndk的...

Android中使用NativeActivity进行APP开发

自古以来,Android的主要开发语言都是以Java为主,也有很多开发者使用其他语言,当然也有混合开发的,比如Java&C or Java&C++等,一直以来,Android的开发语言层出不穷 现在看...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

NativeActivity工程编译及运行

// android-ndk-r8e/samples/native-activity 用eclipse创建一个已经存在的工程,把这个native-activity创建行eclipse即可。具体步骤:...

android,NativeActivity使用

android现在已经支持C/C++ NativeActivity开发 android提供[code lang="c"][/code]头文件。所以你要使用的话,要引入这个头文件 1,Nativ...

Ogre3d 之使用 Android NativeActivity

昨天把Ogre3d 编译到Android 平台安装之后,再回头看代码才发现,在Android工程中居然没有Java源文件,从Manifest文件中才知道原来使用的是 NativeActivity 。这...

容斥原理(模板+例题)

网上找来方便自己看,理解。 容斥原理:在计数时,必须注意无一重复,无一遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象...

注解原理

注解原理 Java内置的注解以及自定义一个注解大家都比较熟悉的了,现在来看看注解实现的原理,看看Java的体系下面是如何对注解的支持的。 在讨论前先看一个自定义注解的例子,自定义实现这样一个注解:...

星号密码查看器原理

星号密码查看器原理     网上很多人写了叫做星号密码查看器的东西,今天大体研究了下,原理很简单,写个测试例子,在说下怎么防护。 原理:    平时编程可能会拖拽这么一个控件,text或者别的类...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)