zoukankan      html  css  js  c++  java
  • Android NDK 更新,不再需要 Java

    想用 C/C++ 开发 Android 应用的开发人员有好消息了,最新版本的 NDK (r5,Android 2.3 姜饼系统) 允许你完全用 C/C++ 来开发应用或者游戏,而不再需要编写任何 Java 的代码。这个更新大大的简化了想使用 C/C++ 开发 Android 应用的工作。同时 Google Android 的开发者增加了一个完整的示例:

    AndroidManifest.xml

    <manifest xmlns:Android="http://schemas.android.com/apk/res/android"
    package
    ="com.example.native_activity"
    Android:versionCode
    ="1"
    Android:versionName
    ="1.0">

    <!-- This is the platform API where NativeActivity was introduced. -->
    <uses-sdk Android:minSdkVersion="8" />

    <!-- This .apk has no Java code itself, so set hasCode to false. -->
    <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 or .so -->
    <meta-data Android:name="android.app.lib_name"
    Android:value
    ="native-activity" />
    <intent-filter>
    <action Android:name="android.intent.action.MAIN" />
    <category Android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    </activity>
    </application>

    </manifest>

    Demo.c

    #include
    <jni.h>
    #include
    <errno.h>

    #include
    <EGL/egl.h>
    #include
    <GLES/gl.h>

    #include
    <Android/sensor.h>
    #include
    <Android/log.h>
    #include
    <Android_native_app_glue.h>

    #define LOGI(...) ((void)__Android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
    #define LOGW(...) ((void)__Android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))

    /**
    * Our saved state data.
    */
    struct saved_state {
    float angle;
    int32_t x;
    int32_t y;
    };

    /**
    * Shared state for our app.
    */
    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;
    };

    /**
    * Initialize an EGL context for the current display.
    */
    static int engine_init_display(struct engine* engine) {
    // initialize OpenGL ES and EGL

    /*
    * Here specify the attributes of the desired configuration.
    * Below, we select an EGLConfig with at least 8 bits per color
    * component compatible with on-screen windows
    */
    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, dummy, format;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;

    EGLDisplay display
    = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    eglInitialize(display,
    0, 0);

    /* Here, the application chooses the configuration it desires. In this
    * sample, we have a very simplified selection process, where we pick
    * the first EGLConfig that matches our criteria
    */
    eglChooseConfig(display, attribs,
    &config, 1, &numConfigs);

    /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
    * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
    * As soon as we picked a EGLConfig, we can safely reconfigure the
    * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID.
    */
    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;

    // Initialize GL state.
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    glEnable(GL_CULL_FACE);
    glShadeModel(GL_SMOOTH);
    glDisable(GL_DEPTH_TEST);

    return 0;
    }

    /**
    * Just the current frame in the display.
    */
    static void engine_draw_frame(struct engine* engine) {
    if (engine->display == NULL) {
    // No display.
    return;
    }

    // Just fill the screen with a color.
    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);
    }

    /**
    * Tear down the EGL context currently associated with the display.
    */
    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;
    }

    /**
    * Process the next input event.
    */
    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
    ->animating = 1;
    engine
    ->state.x = AMotionEvent_getX(event, 0);
    engine
    ->state.y = AMotionEvent_getY(event, 0);
    return 1;
    }
    return 0;
    }

    /**
    * Process the next main command.
    */
    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:
    // The system has asked us to save our current state. Do so.
    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:
    // The window is being shown, get it ready.
    if (engine->app->window != NULL) {
    engine_init_display(engine);
    engine_draw_frame(engine);
    }
    break;
    case APP_CMD_TERM_WINDOW:
    // The window is being hidden or closed, clean it up.
    engine_term_display(engine);
    break;
    case APP_CMD_GAINED_FOCUS:
    // When our app gains focus, we start monitoring the accelerometer.
    if (engine->accelerometerSensor != NULL) {
    ASensorEventQueue_enableSensor(engine
    ->sensorEventQueue,
    engine
    ->accelerometerSensor);
    // We'd like to get 60 events per second (in us).
    ASensorEventQueue_setEventRate(engine->sensorEventQueue,
    engine
    ->accelerometerSensor, (1000L/60)*1000);
    }
    break;
    case APP_CMD_LOST_FOCUS:
    // When our app loses focus, we stop monitoring the accelerometer.
    // This is to avoid consuming battery while not being used.
    if (engine->accelerometerSensor != NULL) {
    ASensorEventQueue_disableSensor(engine
    ->sensorEventQueue,
    engine
    ->accelerometerSensor);
    }
    // Also stop animating.
    engine->animating = 0;
    engine_draw_frame(engine);
    break;
    }
    }

    /**
    * This is the main entry point of a native application that is using
    * Android_native_app_glue. It runs in its own thread, with its own
    * event loop for receiving input events and doing other things.
    */
    void Android_main(struct android_app* state) {
    struct engine engine;

    // Make sure glue isn't stripped.
    app_dummy();

    memset(
    &engine, 0, sizeof(engine));
    state
    ->userData = &engine;
    state
    ->onAppCmd = engine_handle_cmd;
    state
    ->onInputEvent = engine_handle_input;
    engine.app
    = state;

    // Prepare to monitor accelerometer
    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) {
    // We are starting with a previous saved state; restore from it.
    engine.state = *(struct saved_state*)state->savedState;
    }

    // loop waiting for stuff to do.

    while (1) {
    // Read all pending events.
    int ident;
    int events;
    struct Android_poll_source* source;

    // If not animating, we will block forever waiting for events.
    // If animating, we loop until all events are read, then continue
    // to draw the next frame of animation.
    while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
    (
    void**)&source)) >= 0) {

    // Process this event.
    if (source != NULL) {
    source
    ->process(state, source);
    }

    // If a sensor has data, process it now.
    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);
    }
    }
    }

    // Check if we are exiting.
    if (state->destroyRequested != 0) {
    engine_term_display(
    &engine);
    return;
    }
    }

    if (engine.animating) {
    // Done with events; draw next animation frame.
    engine.state.angle += .01f;
    if (engine.state.angle > 1) {
    engine.state.angle
    = 0;
    }

    // Drawing is throttled to the screen update rate, so there
    // is no need to do timing here.
    engine_draw_frame(&engine);
    }
    }
    }

  • 相关阅读:
    (1)java设计模式之简单工厂模式
    QuartZ Cron表达式在java定时框架中的应用
    java.lang.OutOfMemoryError:GC overhead limit exceeded填坑心得
    https实现安全传输的流程
    liunx上运行mybase
    liux之sed用法
    java并发之CyclicBarrier
    java并发之Semaphore
    关于ConcurrentSkipListMap的理解
    java中Iterator和ListIterator的区别与联系
  • 原文地址:https://www.cnblogs.com/hicjiajia/p/1940022.html
Copyright © 2011-2022 走看看