美文网首页
构建NativeActivity 没有dex 没有java代码的

构建NativeActivity 没有dex 没有java代码的

作者: 吉凶以情迁 | 来源:发表于2018-10-21 19:17 被阅读0次

    干了几年安卓开发 ,某次经历刷新了我的世界观了
    清单文件application节点设置为
    <application android:label="@string/app_name" android:hasCode="false">就可以实现了。

    定义application节点

    
        <application android:label="@string/app_name" android:hasCode="false">
    
            <!-- Our activity is the built-in NativeActivity framework class.
                 This will take care of integrating with our NDK code. -->
            <activity android:name="android.app.NativeActivity" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden">
                <!-- Tell NativeActivity the name of our .so -->
                <meta-data android:name="android.app.lib_name" android:value="$(AndroidAppLibName)"/>
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    

    完整的

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.AndroidNativeActivity" platformBuildVersionCode="21" platformBuildVersionName="5.0.1-1624448">
        <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="21" />
        <application android:label="@string/app_name" android:hasCode="false" android:debuggable="true">
            <activity android:label="@string/app_name" android:name="android.app.NativeActivity" android:configChanges="keyboardHidden|orientation">
                <meta-data android:name="android.app.lib_name" android:value="AndroidNativeActivity" />
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>
    

    其中AndroidNativeActivity就是libAndroidNativeActivity.so

    入口函数void android_main(struct android_app* state) {

    完整c代码

    /*
     * 版权所有 (C) 2010 Android 开放源码代码项目
     *
     * 按照 Apache 许可 2.0 版本(称为“许可”)授予许可;
     * 要使用此文件,必须遵循“许可”中的说明。
     * 你可以从以下位置获取“许可”的副本
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * 除非适用法律要求或书面同意,根据
     * “许可”分配的软件“按原样”分配,
     * 不提供任何形式(无论是明示还是默示)的担保和条件。
     * 参见“许可”了解“许可”中管理权限和
     * 限制的指定语言。
     *
    */
    
    #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "AndroidProject1.NativeActivity", __VA_ARGS__))
    #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "AndroidProject1.NativeActivity", __VA_ARGS__))
    
    /**
    * 我们的保存状态数据。
    */
    struct saved_state {
        float angle;
        int32_t x;
        int32_t y;
    };
    
    /**
    * 我们应用程序的共享状态。
    */
    struct engine {
        struct android_app* app;
    
        ASensorManager* sensorManager;
        const ASensor* accelerometerSensor;
        ASensorEventQueue* sensorEventQueue;
    
        int animating;
        EGLDisplay display;
        EGLSurface surface;
        EGLContext context;
        int32_t width;
        int32_t height;
        struct saved_state state;
    };
    
    /**
    * 初始化当前显示的 EGL 上下文。
    */
    static int engine_init_display(struct engine* engine) {
        //初始化 OpenGL ES 和 EGL
    
        /*
        * 此处指定了所需配置的属性。
        *下面,我们选择与屏上窗口
        * 兼容的至少每个颜色有 8 个位的 EGLConfig 
        */
        const EGLint attribs[] = {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
            EGL_BLUE_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_RED_SIZE, 8,
            EGL_NONE
        };
        EGLint w, h, format;
        EGLint numConfigs;
        EGLConfig config;
        EGLSurface surface;
        EGLContext context;
    
        EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    
        eglInitialize(display, 0, 0);
    
        /*此处,应用程序选择了所需的配置。 在本
        *示例中,我们有非常简化的选择流程,
        *其中我们选取了与我们的标准匹配的第一个 EGLConfig */
        eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    
        /* EGL_NATIVE_VISUAL_ID 是
        *保证会被 ANativeWindow_setBuffersGeometry() 接受的 EGLConfig 的属性。
        * 只要我们选取 EGLConfig,就可使用 EGL_NATIVE_VISUAL_ID 安全地重新配置
        * ANativeWindow 缓冲区以进行匹配。*/
        eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
    
        ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
    
        surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
        context = eglCreateContext(display, config, NULL, NULL);
    
        if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
            LOGW("Unable to eglMakeCurrent");
            return -1;
        }
    
        eglQuerySurface(display, surface, EGL_WIDTH, &w);
        eglQuerySurface(display, surface, EGL_HEIGHT, &h);
    
        engine->display = display;
        engine->context = context;
        engine->surface = surface;
        engine->width = w;
        engine->height = h;
        engine->state.angle = 0;
    
        //初始化 GL 状态。
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
        glEnable(GL_CULL_FACE);
        glShadeModel(GL_SMOOTH);
        glDisable(GL_DEPTH_TEST);
    
        return 0;
    }
    
    /**
    * 仅显示中的当前帧。
    */
    static void engine_draw_frame(struct engine* engine) {
        if (engine->display == NULL) {
            //无显示。
            return;
        }
    
        //只使用一种颜色填充屏幕。
        glClearColor(((float)engine->state.x) / engine->width, engine->state.angle,
            ((float)engine->state.y) / engine->height, 1);
        glClear(GL_COLOR_BUFFER_BIT);
    
        eglSwapBuffers(engine->display, engine->surface);
    }
    
    /**
    * 关闭当前与显示关联的 EGL 上下文。
    */
    static void engine_term_display(struct engine* engine) {
        if (engine->display != EGL_NO_DISPLAY) {
            eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            if (engine->context != EGL_NO_CONTEXT) {
                eglDestroyContext(engine->display, engine->context);
            }
            if (engine->surface != EGL_NO_SURFACE) {
                eglDestroySurface(engine->display, engine->surface);
            }
            eglTerminate(engine->display);
        }
        engine->animating = 0;
        engine->display = EGL_NO_DISPLAY;
        engine->context = EGL_NO_CONTEXT;
        engine->surface = EGL_NO_SURFACE;
    }
    
    /**
    *处理下一输入事件。
    */
    static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
        struct engine* engine = (struct engine*)app->userData;
        if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
            engine->state.x = AMotionEvent_getX(event, 0);
            engine->state.y = AMotionEvent_getY(event, 0);
            return 1;
        }
        return 0;
    }
    
    /**
    *处理下一主命令。
    */
    static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
        struct engine* engine = (struct engine*)app->userData;
        switch (cmd) {
        case APP_CMD_SAVE_STATE:
            //系统已经要求我们保存当前状态。就这样做。
            engine->app->savedState = malloc(sizeof(struct saved_state));
            *((struct saved_state*)engine->app->savedState) = engine->state;
            engine->app->savedStateSize = sizeof(struct saved_state);
            break;
        case APP_CMD_INIT_WINDOW:
            //正在显示窗口,让其准备就绪。
            if (engine->app->window != NULL) {
                engine_init_display(engine);
                engine_draw_frame(engine);
            }
            break;
        case APP_CMD_TERM_WINDOW:
            //正在隐藏或关闭窗口,请其进行清理。
            engine_term_display(engine);
            break;
        case APP_CMD_GAINED_FOCUS:
            //当我们的应用获得焦点时,我们开始监控加速计。
            if (engine->accelerometerSensor != NULL) {
                ASensorEventQueue_enableSensor(engine->sensorEventQueue,
                    engine->accelerometerSensor);
                //我们想要每秒获得 60 个事件(在美国)。
                ASensorEventQueue_setEventRate(engine->sensorEventQueue,
                    engine->accelerometerSensor, (1000L / 60) * 1000);
            }
            break;
        case APP_CMD_LOST_FOCUS:
            //当我们的应用程序失去焦点时,我们会停止监控加速计。
            //这可在不使用时避免使用电池。
            if (engine->accelerometerSensor != NULL) {
                ASensorEventQueue_disableSensor(engine->sensorEventQueue,
                    engine->accelerometerSensor);
            }
            //另外,停止动画。
            engine->animating = 0;
            engine_draw_frame(engine);
            break;
        }
    }
    
    /**
    * 这是使用 android_native_app_glue
    * 的本地应用程序的主要入口点。它在其自己的线程中运行,具有自己的
    * 事件循环用于接收输入事件并执行其他操作。
    */
    void android_main(struct android_app* state) {
        struct engine engine;
    
        memset(&engine, 0, sizeof(engine));
        state->userData = &engine;
        state->onAppCmd = engine_handle_cmd;
        state->onInputEvent = engine_handle_input;
        engine.app = state;
    
        //准备监控加速器
        engine.sensorManager = ASensorManager_getInstance();
        engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
            ASENSOR_TYPE_ACCELEROMETER);
        engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
            state->looper, LOOPER_ID_USER, NULL, NULL);
    
        if (state->savedState != NULL) {
            //我们从之前保存的状态开始;从它还原。
            engine.state = *(struct saved_state*)state->savedState;
        }
    
        engine.animating = 1;
    
        //循环等待事情以进行处理。
    
        while (1) {
            //读取所有挂起的事件。
            int ident;
            int events;
            struct android_poll_source* source;
    
            //如果没有动态效果,我们将一直阻止等待事件。
            //如果有动态效果,我们进行循环,直到读取所有事件,然后继续
            //绘制动画的下一帧。
            while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
                (void**)&source)) >= 0) {
    
                //处理此事件。
                if (source != NULL) {
                    source->process(state, source);
                }
    
                //如果传感器有数据,立即处理。
                if (ident == LOOPER_ID_USER) {
                    if (engine.accelerometerSensor != NULL) {
                        ASensorEvent event;
                        while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
                            &event, 1) > 0) {
                            LOGI("accelerometer: x=%f y=%f z=%f",
                                event.acceleration.x, event.acceleration.y,
                                event.acceleration.z);
                        }
                    }
                }
    
                //检查,我们是否存在。
                if (state->destroyRequested != 0) {
                    engine_term_display(&engine);
                    return;
                }
            }
    
            if (engine.animating) {
                //事件完成;绘制下一动画帧。
                engine.state.angle += .01f;
                if (engine.state.angle > 1) {
                    engine.state.angle = 0;
                }
    
                //绘图被降低到屏幕更新速率,
                //因此,没有必要在此处计时。
                engine_draw_frame(&engine);
            }
        }
    }
    
    

    某c

    /*
     * 版权所有 (C) 2010 Android 开放源代码项目
     *
     * 按照 Apache 许可 2.0 版本(称为“许可”)授予许可;
     * 要使用此文件,必须遵循“许可”中的说明。
     * 你可以从以下位置获取“许可”的副本
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * 除非适用法律要求或书面同意,根据
     * “许可”分配的软件“按原样”分配,
     * 不提供任何形式(无论是明示还是默示)的担保和条件。
     * 参见“许可”了解“许可”中管理权限和
     * 限制的指定语言。
     *
     */
    
    #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
    #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
    
    /*对于调试版本,始终在此库中启用调试跟踪*/
    #ifndef NDEBUG
    #  define LOGV(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
    #else
    #  define LOGV(...)  ((void)0)
    #endif
    
    static void free_saved_state(struct android_app* android_app) {
        pthread_mutex_lock(&android_app->mutex);
        if (android_app->savedState != NULL) {
            free(android_app->savedState);
            android_app->savedState = NULL;
            android_app->savedStateSize = 0;
        }
        pthread_mutex_unlock(&android_app->mutex);
    }
    
    int8_t android_app_read_cmd(struct android_app* android_app) {
        int8_t cmd;
        if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
            switch (cmd) {
                case APP_CMD_SAVE_STATE:
                    free_saved_state(android_app);
                    break;
            }
            return cmd;
        } else {
            LOGE("No data on command pipe!");
        }
        return -1;
    }
    
    static void print_cur_config(struct android_app* android_app) {
        char lang[2], country[2];
        AConfiguration_getLanguage(android_app->config, lang);
        AConfiguration_getCountry(android_app->config, country);
    
        LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
                "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
                "modetype=%d modenight=%d",
                AConfiguration_getMcc(android_app->config),
                AConfiguration_getMnc(android_app->config),
                lang[0], lang[1], country[0], country[1],
                AConfiguration_getOrientation(android_app->config),
                AConfiguration_getTouchscreen(android_app->config),
                AConfiguration_getDensity(android_app->config),
                AConfiguration_getKeyboard(android_app->config),
                AConfiguration_getNavigation(android_app->config),
                AConfiguration_getKeysHidden(android_app->config),
                AConfiguration_getNavHidden(android_app->config),
                AConfiguration_getSdkVersion(android_app->config),
                AConfiguration_getScreenSize(android_app->config),
                AConfiguration_getScreenLong(android_app->config),
                AConfiguration_getUiModeType(android_app->config),
                AConfiguration_getUiModeNight(android_app->config));
    }
    
    void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
        switch (cmd) {
            case APP_CMD_INPUT_CHANGED:
                LOGV("APP_CMD_INPUT_CHANGED\n");
                pthread_mutex_lock(&android_app->mutex);
                if (android_app->inputQueue != NULL) {
                    AInputQueue_detachLooper(android_app->inputQueue);
                }
                android_app->inputQueue = android_app->pendingInputQueue;
                if (android_app->inputQueue != NULL) {
                    LOGV("Attaching input queue to looper");
                    AInputQueue_attachLooper(android_app->inputQueue,
                            android_app->looper, LOOPER_ID_INPUT, NULL,
                            &android_app->inputPollSource);
                }
                pthread_cond_broadcast(&android_app->cond);
                pthread_mutex_unlock(&android_app->mutex);
                break;
    
            case APP_CMD_INIT_WINDOW:
                LOGV("APP_CMD_INIT_WINDOW\n");
                pthread_mutex_lock(&android_app->mutex);
                android_app->window = android_app->pendingWindow;
                pthread_cond_broadcast(&android_app->cond);
                pthread_mutex_unlock(&android_app->mutex);
                break;
    
            case APP_CMD_TERM_WINDOW:
                LOGV("APP_CMD_TERM_WINDOW\n");
                pthread_cond_broadcast(&android_app->cond);
                break;
    
            case APP_CMD_RESUME:
            case APP_CMD_START:
            case APP_CMD_PAUSE:
            case APP_CMD_STOP:
                LOGV("activityState=%d\n", cmd);
                pthread_mutex_lock(&android_app->mutex);
                android_app->activityState = cmd;
                pthread_cond_broadcast(&android_app->cond);
                pthread_mutex_unlock(&android_app->mutex);
                break;
    
            case APP_CMD_CONFIG_CHANGED:
                LOGV("APP_CMD_CONFIG_CHANGED\n");
                AConfiguration_fromAssetManager(android_app->config,
                        android_app->activity->assetManager);
                print_cur_config(android_app);
                break;
    
            case APP_CMD_DESTROY:
                LOGV("APP_CMD_DESTROY\n");
                android_app->destroyRequested = 1;
                break;
        }
    }
    
    void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
        switch (cmd) {
            case APP_CMD_TERM_WINDOW:
                LOGV("APP_CMD_TERM_WINDOW\n");
                pthread_mutex_lock(&android_app->mutex);
                android_app->window = NULL;
                pthread_cond_broadcast(&android_app->cond);
                pthread_mutex_unlock(&android_app->mutex);
                break;
    
            case APP_CMD_SAVE_STATE:
                LOGV("APP_CMD_SAVE_STATE\n");
                pthread_mutex_lock(&android_app->mutex);
                android_app->stateSaved = 1;
                pthread_cond_broadcast(&android_app->cond);
                pthread_mutex_unlock(&android_app->mutex);
                break;
    
            case APP_CMD_RESUME:
                free_saved_state(android_app);
                break;
        }
    }
    
    static void android_app_destroy(struct android_app* android_app) {
        LOGV("android_app_destroy!");
        free_saved_state(android_app);
        pthread_mutex_lock(&android_app->mutex);
        if (android_app->inputQueue != NULL) {
            AInputQueue_detachLooper(android_app->inputQueue);
        }
        AConfiguration_delete(android_app->config);
        android_app->destroyed = 1;
        pthread_cond_broadcast(&android_app->cond);
        pthread_mutex_unlock(&android_app->mutex);
        //此后,无法接触 android_app 项目。
    }
    
    static void process_input(struct android_app* app, struct android_poll_source* source) {
        AInputEvent* event = NULL;
        while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
            LOGV("New input event: type=%d\n", AInputEvent_getType(event));
            if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
                continue;
            }
            int32_t handled = 0;
            if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
            AInputQueue_finishEvent(app->inputQueue, event, handled);
        }
    }
    
    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* android_app_entry(void* param) {
        struct android_app* android_app = (struct android_app*)param;
    
        android_app->config = AConfiguration_new();
        AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
    
        print_cur_config(android_app);
    
        android_app->cmdPollSource.id = LOOPER_ID_MAIN;
        android_app->cmdPollSource.app = android_app;
        android_app->cmdPollSource.process = process_cmd;
        android_app->inputPollSource.id = LOOPER_ID_INPUT;
        android_app->inputPollSource.app = android_app;
        android_app->inputPollSource.process = process_input;
    
        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;
        pthread_cond_broadcast(&android_app->cond);
        pthread_mutex_unlock(&android_app->mutex);
    
        android_main(android_app);
    
        android_app_destroy(android_app);
        return NULL;
    }
    
    // --------------------------------------------------------------------
    //本地活动交互(从主线程调用)
    // --------------------------------------------------------------------
    
    static struct android_app* android_app_create(ANativeActivity* activity,
            void* savedState, size_t savedStateSize) {
        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;
    
        pthread_mutex_init(&android_app->mutex, NULL);
        pthread_cond_init(&android_app->cond, NULL);
    
        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);
        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);
    
        return android_app;
    }
    
    static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
        if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
            LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
        }
    }
    
    static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
        pthread_mutex_lock(&android_app->mutex);
        android_app->pendingInputQueue = inputQueue;
        android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
        while (android_app->inputQueue != android_app->pendingInputQueue) {
            pthread_cond_wait(&android_app->cond, &android_app->mutex);
        }
        pthread_mutex_unlock(&android_app->mutex);
    }
    
    static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
        pthread_mutex_lock(&android_app->mutex);
        if (android_app->pendingWindow != NULL) {
            android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
        }
        android_app->pendingWindow = window;
        if (window != NULL) {
            android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
        }
        while (android_app->window != android_app->pendingWindow) {
            pthread_cond_wait(&android_app->cond, &android_app->mutex);
        }
        pthread_mutex_unlock(&android_app->mutex);
    }
    
    static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
        pthread_mutex_lock(&android_app->mutex);
        android_app_write_cmd(android_app, cmd);
        while (android_app->activityState != cmd) {
            pthread_cond_wait(&android_app->cond, &android_app->mutex);
        }
        pthread_mutex_unlock(&android_app->mutex);
    }
    
    static void android_app_free(struct android_app* android_app) {
        pthread_mutex_lock(&android_app->mutex);
        android_app_write_cmd(android_app, APP_CMD_DESTROY);
        while (!android_app->destroyed) {
            pthread_cond_wait(&android_app->cond, &android_app->mutex);
        }
        pthread_mutex_unlock(&android_app->mutex);
    
        close(android_app->msgread);
        close(android_app->msgwrite);
        pthread_cond_destroy(&android_app->cond);
        pthread_mutex_destroy(&android_app->mutex);
        free(android_app);
    }
    
    static void onDestroy(ANativeActivity* activity) {
        LOGV("Destroy: %p\n", activity);
        android_app_free((struct android_app*)activity->instance);
    }
    
    static void onStart(ANativeActivity* activity) {
        LOGV("Start: %p\n", activity);
        android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
    }
    
    static void onResume(ANativeActivity* activity) {
        LOGV("Resume: %p\n", activity);
        android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
    }
    
    static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
        struct android_app* android_app = (struct android_app*)activity->instance;
        void* savedState = NULL;
    
        LOGV("SaveInstanceState: %p\n", activity);
        pthread_mutex_lock(&android_app->mutex);
        android_app->stateSaved = 0;
        android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
        while (!android_app->stateSaved) {
            pthread_cond_wait(&android_app->cond, &android_app->mutex);
        }
    
        if (android_app->savedState != NULL) {
            savedState = android_app->savedState;
            *outLen = android_app->savedStateSize;
            android_app->savedState = NULL;
            android_app->savedStateSize = 0;
        }
    
        pthread_mutex_unlock(&android_app->mutex);
    
        return savedState;
    }
    
    static void onPause(ANativeActivity* activity) {
        LOGV("Pause: %p\n", activity);
        android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
    }
    
    static void onStop(ANativeActivity* activity) {
        LOGV("Stop: %p\n", activity);
        android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
    }
    
    static void onConfigurationChanged(ANativeActivity* activity) {
        struct android_app* android_app = (struct android_app*)activity->instance;
        LOGV("ConfigurationChanged: %p\n", activity);
        android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
    }
    
    static void onLowMemory(ANativeActivity* activity) {
        struct android_app* android_app = (struct android_app*)activity->instance;
        LOGV("LowMemory: %p\n", activity);
        android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
    }
    
    static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
        LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
        android_app_write_cmd((struct android_app*)activity->instance,
                focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
    }
    
    static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
        LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
        android_app_set_window((struct android_app*)activity->instance, window);
    }
    
    static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
        LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
        android_app_set_window((struct android_app*)activity->instance, NULL);
    }
    
    static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
        LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
        android_app_set_input((struct android_app*)activity->instance, queue);
    }
    
    static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
        LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
        android_app_set_input((struct android_app*)activity->instance, NULL);
    }
    
    void ANativeActivity_onCreate(ANativeActivity* activity,
            void* savedState, size_t savedStateSize) {
        LOGV("Creating: %p\n", activity);
        activity->callbacks->onDestroy = onDestroy;
        activity->callbacks->onStart = onStart;
        activity->callbacks->onResume = onResume;
        activity->callbacks->onSaveInstanceState = onSaveInstanceState;
        activity->callbacks->onPause = onPause;
        activity->callbacks->onStop = onStop;
        activity->callbacks->onConfigurationChanged = onConfigurationChanged;
        activity->callbacks->onLowMemory = onLowMemory;
        activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
        activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
        activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
        activity->callbacks->onInputQueueCreated = onInputQueueCreated;
        activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
    
        activity->instance = android_app_create(activity, savedState, savedStateSize);
    }
    
    

    某h

    /*
     * 版权所有 (C) 2010 Android 开放源代码项目
     *
     * 按照 Apache 许可 2.0 版本(称为“许可”)授予许可;
     * 要使用此文件,必须遵循“许可”中的说明。
     * 你可以从以下位置获取“许可”的副本
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * 除非适用法律要求或书面同意,根据
     * “许可”分配的软件“按原样”分配,
     * 不提供任何形式(无论是明示还是默示)的担保和条件。
     * 参见“许可”了解“许可”中管理权限和
     * 限制的指定语言。
     *
     */
    
    #ifndef _ANDROID_NATIVE_APP_GLUE_H
    #define _ANDROID_NATIVE_APP_GLUE_H
    
    #include <poll.h>
    #include <pthread.h>
    #include <sched.h>
    
    #include <android/configuration.h>
    #include <android/looper.h>
    #include <android/native_activity.h>
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /**
     * 由 <android/native_activity.h> 提供的本地活动界面
     * 基于一组应用程序提供的回调,
     * 发生某些事件时,活动的主线程将调用这些回调。
     *
     * 这意味着,这些回调中的每个回调不应堵塞,否则会有系统
     * 强制关闭应用程序的风险。此编程
     * 模型直接、轻型,但是有约束。
     *
     *“threaded_native_app”静态库用于提供不同的
     * 执行模型,其中应用程序可在其他
     * 线程中实施它自己的主要事件循环。其工作方式如下:
     *
     * 1/ 应用程序必须提供名为“android_main()”的函数,
     *    当在不同于活动的主线程的
     *    新线程中创建活动时,将调用该函数。
     *
     * 2/ android_main() 接收到指向有效的“android_app”结构的指针,
     *    该结构包含对其他重要对象(例如,
     *    应用程序正在其中运行的 ANativeActivity 对象实例)的引用。
     *
     * 3/“android_app”对象保留已经
     *    在侦听以下两项重大事件的 ALooper 实例:
     *
     *      - 活动生命周期事件(例如“暂停”、“恢复”)。参见下文的 APP_CMD_XXX
     *        声明。
     *
     *      - 来自附加到活动的 AInputQueue 的输入事件。
     *
     *    每个事件都对应于一个由值分别为 LOOPER_ID_MAIN 和 LOOPER_ID_INPUT 的
     *    ALooper_pollOnce 返回的 ALooper
     *    标识符。
     *
     *    你的应用程序可使用相同的 ALooper 侦听其他
     *    文件描述符。它们可基于回调或带有以
     *    LOOPER_ID_USER 开头的返回标识符。
     *
     * 4/ 无论在何时收到 LOOPER_ID_MAIN 或 LOOPER_ID_INPUT 事件,
     *    返回的数据都将指向 android_poll_source 结构。你
     *    可对它调用 process() 函数,并填入要调用的 android_app->onAppCmd
     *    和 android_app->onInputEvent,以处理你自己的
     *    事件。
     *
     *    另外,你还可调用低级别函数直接
     *    读取和处理数据...  查看附加的 process_cmd() 和 process_input()
     *    实现,以了解如何进行此操作。
     *
     * 查看包含完整用例的 NDK 中提供的名为 
     *“native-activity”的示例。另请查看 NativeActivity 的 JavaDoc。
     */
    
    struct android_app;
    
    /**
     * 当该源的数据准备就绪后,
     * 与 ALooper fd 相关的数据将作为“outData”返回。
     */
    struct android_poll_source {
        //此源的标识符。  可能是 LOOPER_ID_MAIN 或
        // LOOPER_ID_INPUT。
        int32_t id;
    
        //此 ident 关联的 android_app。
        struct android_app* app;
    
        //要从此源调用以执行标准数据处理的
        //函数。
        void (*process)(struct android_app* app, struct android_poll_source* source);
    };
    
    /**
     * 这是针对线程化应用程序的标准粘附代码的
     * 界面。 在此模型中,应用程序的代码在
     * 其自己的线程中运行,该线程独立于进程的主线程。
     * 此线程不必与 Java
     * VM 关联,尽管它们需要相互关联以使 JNI 调用任何
     *  Java 对象。
     */
    struct android_app {
        //如果愿意,应用程序可将指向其自己的状态对象的指针
        //放在这里。
        void* userData;
    
        //在此处填充用于处理主应用命令(APP_CMD_*)的函数
        void (*onAppCmd)(struct android_app* app, int32_t cmd);
    
        //在此处填充用于处理输入事件的函数。此时,
        //事件已经提前分派,一经返回将立即
        //完成。如果你已处理该事件,则返回 1,对于任何默认
        //分派返回 0。
        int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
    
        //此应用在其中运行的 ANativeActivity 对象实例。
        ANativeActivity* activity;
    
        //正在运行的应用采用的当前配置。
        AConfiguration* config;
    
        //这是创建时提供的上一个实例的已保存状态。
        //如果没有状态,则为 NULL。你可根据需要使用;
        //内存将保持可用,直到你为 APP_CMD_RESUME 调用 android_app_exec_cmd(),
        //此时,将释放内存,并且 savedState 设置为 NULL。
        //仅当处理 APP_CMD_SAVE_STATE 时才可更改这些变量,
        //此时,这些变量将初始化为 NULL,并且你能够为你的
        //状态分配内存并将信息放在此处。这种情况下,将稍后
        //为你释放内存。
        void* savedState;
        size_t savedStateSize;
    
        //与应用的线程关联的 ALooper。
        ALooper* looper;
    
        //不为 NULL 时,这是一个输入队列,应用将通过它
        //接收用户输入序列。
        AInputQueue* inputQueue;
    
        //不为 NIULL 时,这是应用可在其中进行绘制的窗口界面。
        ANativeWindow* window;
    
        //窗口的当前内容矩形;这是
        //应放置窗口的内容以供用户查看的区域。
        ARect contentRect;
    
        //应用的活动的当前状态。可能是 APP_CMD_START、
        //APP_CMD_RESUME、APP_CMD_PAUSE 或 APP_CMD_STOP;请参见下文。
        int activityState;
    
        //应用程序的 NativeActivity 被破坏并且正在
        //等待应用线程完成时,这为非零值。
        int destroyRequested;
    
        // -------------------------------------------------
        //以下是粘附代码的“私有”实现。
    
        pthread_mutex_t mutex;
        pthread_cond_t cond;
    
        int msgread;
        int msgwrite;
    
        pthread_t thread;
    
        struct android_poll_source cmdPollSource;
        struct android_poll_source inputPollSource;
    
        int running;
        int stateSaved;
        int destroyed;
        int redrawNeeded;
        AInputQueue* pendingInputQueue;
        ANativeWindow* pendingWindow;
        ARect pendingContentRect;
    };
    
    enum {
        /**
         *命令的 Looper 数据 ID,其中的命令来自应用的主线程,该数据 ID 作为一个标识符从
         *ALooper_pollOnce() 返回。  此
         * 标识符的数据是指向 android_poll_source structure 结构的指针。
         * 可使用 android_app_read_cmd()
         * 和 android_app_exec_cmd() 检索和处理这些数据。
         */
        LOOPER_ID_MAIN = 1,
    
        /**
         * 事件的 Looper 数据 ID,其中的事件来自应用程序窗口的 AInputQueue,
         * 该数据 ID 作为一个标识符从
         * ALooper_pollOnce() 返回。此标识符的数据是指向
         * android_poll_source 结构的指针。这些数据可通过
         *android_app 的 inputQueue 对象读取。
         */
        LOOPER_ID_INPUT = 2,
    
        /**
         * 用户定义的 ALooper 标识符的开头。
         */
        LOOPER_ID_USER = 3,
    };
    
    enum {
        /**
         * 来自主线程的命令: AInputQueue 已更改。  处理
         * 此命令时,android_app->inputQueue 将更新到新的队列
         * (或 NULL)。
         */
        APP_CMD_INPUT_CHANGED,
    
        /**
         * 来自主线程的命令: 新的 ANativeWindow 已准备就绪可供使用。  接收到
         * 此命令后,android_app->window 将包含新的窗口
         * 界面。
         */
        APP_CMD_INIT_WINDOW,
    
        /**
         * 来自主线程的命令: 需要终止
         * 目前的 ANativeWindow。  收到此命令后,android_app->window 仍
         * 包含现有窗口;调用 android_app_exec_cmd 后,
         * 它将被设置为 NULL。
         */
        APP_CMD_TERM_WINDOW,
    
        /**
         * 来自主线程的命令: 已调整当前 ANativeWindow 的大小。
         * 请根据它的新大小重新绘制。
         */
        APP_CMD_WINDOW_RESIZED,
    
        /**
         * 来自主线程的命令: 系统需要重新绘制
         * 当前 ANativeWindow。  你应该在进行相关处理之前将窗口重新绘制到
         * android_app_exec_cmd(),以避免短暂的绘制故障。
         */
        APP_CMD_WINDOW_REDRAW_NEEDED,
    
        /**
         *来自主线程的命令: 窗口的内容区域已更改,
         * 例如,从显示或隐藏的软输入窗口更改为其他区域。  你可在
         *android_app::contentRect 中找到新的内容矩形。
         */
        APP_CMD_CONTENT_RECT_CHANGED,
    
        /**
         * 来自主线程的命令: 应用的活动窗口已获得
         * 输入焦点。
         */
        APP_CMD_GAINED_FOCUS,
    
        /**
         * 来自主线程的命令: 应用的活动窗口已丢失
         *输入焦点。
         */
        APP_CMD_LOST_FOCUS,
    
        /**
         * 来自主线程的命令: 当前设备配置已更改。
         */
        APP_CMD_CONFIG_CHANGED,
    
        /**
         * 来自主线程的命令: 系统在运行时内存不足。
         * 尝试减少你的内存使用。
         */
        APP_CMD_LOW_MEMORY,
    
        /**
         * 来自主线程的命令: 应用的活动已启动。
         */
        APP_CMD_START,
    
        /**
         * 来自主线程的命令: 应用的活动已恢复。
         */
        APP_CMD_RESUME,
    
        /**
         * 来自主线程的命令: 应用应为它自己生成新的已保存状态,
         * 以便今后在需要时从其进行还原。  如果你有已保存状态,
         * 通过分配内存对其进行分配并将其以
         * android_app.savedStateSize 中的大小放在 android_app.savedState 中。  这样会稍后为你
         * 释放内存。
         */
        APP_CMD_SAVE_STATE,
    
        /**
         * 来自主线程的命令: 应用的活动已暂停。
         */
        APP_CMD_PAUSE,
    
        /**
         * 来自主线程的命令: 应用的活动已停止。
         */
        APP_CMD_STOP,
    
        /**
         * 来自主线程的命令: 应用的活动已被破坏,
         * 正在等待应用程清理并退出,然后继续。
         */
        APP_CMD_DESTROY,
    };
    
    /**
     * ALooper_pollAll() 返回 LOOPER_ID_MAIN 时调用,读取下一
     * 应用命令消息。
     */
    int8_t android_app_read_cmd(struct android_app* android_app);
    
    /**
     * 用 android_app_read_cmd() 返回的命令调用,以对
     * 给定的命令进行初始预处理。调用此函数后,你可对
     * 命令执行你自己的操作。
     */
    void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
    
    /**
     * 用 android_app_read_cmd() 返回的命令调用,以对
     * 给定的命令进行最终后处理。调用此函数前,必须先对
     * 命令执行你自己的操作。
     */
    void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
    
    /**
     * 这是应用程序代码必须实现的函数,表示
     * 应用的主索引项。
     */
    extern void android_main(struct android_app* app);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* _ANDROID_NATIVE_APP_GLUE_H */
    
    

    相关文章

      网友评论

          本文标题:构建NativeActivity 没有dex 没有java代码的

          本文链接:https://www.haomeiwen.com/subject/pnfizftx.html