2013年1月27日 星期日

无Java开发Android应用(NativeActivity)

最新的 Android 2.3 无需 Java 就可以开发应用,详情请看 这里
这里是官方给的例子程序 ,来自:http://developer.android.com/reference/android/app/NativeActivity.html

代码片段(2)

[代码] AndroidManifest.xml

01<manifest xmlns:android="http://schemas.android.com/apk/res/android"
02        package="com.example.native_activity"
03        android:versionCode="1"
04        android:versionName="1.0">
05  
06    <!-- This is the platform API where NativeActivity was introduced. -->
07    <uses-sdk android:minSdkVersion="8" />
08  
09    <!-- This .apk has no Java code itself, so set hasCode to false. -->
10    <application android:label="@string/app_name" android:hasCode="false">
11  
12        <!-- Our activity is the built-in NativeActivity framework class.
13             This will take care of integrating with our NDK code. -->
14        <activity android:name="android.app.NativeActivity"
15                android:label="@string/app_name"
16                android:configChanges="orientation|keyboardHidden">
17            <!-- Tell NativeActivity the name of or .so -->
18            <meta-data android:name="android.app.lib_name"
19                    android:value="native-activity" />
20            <intent-filter>
21                <action android:name="android.intent.action.MAIN" />
22                <category android:name="android.intent.category.LAUNCHER" />
23            </intent-filter>
24        </activity>
25    </application>
26  
27</manifest>

[代码] Demo.c

001#include <jni.h>
002#include <errno.h>
003  
004#include <EGL/egl.h>
005#include <GLES/gl.h>
006  
007#include <android/sensor.h>
008#include <android/log.h>
009#include <android_native_app_glue.h>
010  
011#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
012#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
013  
014/**
015 * Our saved state data.
016 */
017struct saved_state {
018    float angle;
019    int32_t x;
020    int32_t y;
021};
022  
023/**
024 * Shared state for our app.
025 */
026struct engine {
027    struct android_app* app;
028  
029    ASensorManager* sensorManager;
030    const ASensor* accelerometerSensor;
031    ASensorEventQueue* sensorEventQueue;
032  
033    int animating;
034    EGLDisplay display;
035    EGLSurface surface;
036    EGLContext context;
037    int32_t width;
038    int32_t height;
039    struct saved_state state;
040};
041  
042/**
043 * Initialize an EGL context for the current display.
044 */
045static int engine_init_display(struct engine* engine) {
046    // initialize OpenGL ES and EGL
047  
048    /*
049     * Here specify the attributes of the desired configuration.
050     * Below, we select an EGLConfig with at least 8 bits per color
051     * component compatible with on-screen windows
052     */
053    const EGLint attribs[] = {
054            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
055            EGL_BLUE_SIZE, 8,
056            EGL_GREEN_SIZE, 8,
057            EGL_RED_SIZE, 8,
058            EGL_NONE
059    };
060    EGLint w, h, dummy, format;
061    EGLint numConfigs;
062    EGLConfig config;
063    EGLSurface surface;
064    EGLContext context;
065  
066    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
067  
068    eglInitialize(display, 0, 0);
069  
070    /* Here, the application chooses the configuration it desires. In this
071     * sample, we have a very simplified selection process, where we pick
072     * the first EGLConfig that matches our criteria */
073    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
074  
075    /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
076     * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
077     * As soon as we picked a EGLConfig, we can safely reconfigure the
078     * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
079    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
080  
081    ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
082  
083    surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
084    context = eglCreateContext(display, config, NULL, NULL);
085  
086    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
087        LOGW("Unable to eglMakeCurrent");
088        return -1;
089    }
090  
091    eglQuerySurface(display, surface, EGL_WIDTH, &w);
092    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
093  
094    engine->display = display;
095    engine->context = context;
096    engine->surface = surface;
097    engine->width = w;
098    engine->height = h;
099    engine->state.angle = 0;
100  
101    // Initialize GL state.
102    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
103    glEnable(GL_CULL_FACE);
104    glShadeModel(GL_SMOOTH);
105    glDisable(GL_DEPTH_TEST);
106  
107    return 0;
108}
109  
110/**
111 * Just the current frame in the display.
112 */
113static void engine_draw_frame(struct engine* engine) {
114    if (engine->display == NULL) {
115        // No display.
116        return;
117    }
118  
119    // Just fill the screen with a color.
120    glClearColor(((float)engine->state.x)/engine->width, engine->state.angle,
121            ((float)engine->state.y)/engine->height, 1);
122    glClear(GL_COLOR_BUFFER_BIT);
123  
124    eglSwapBuffers(engine->display, engine->surface);
125}
126  
127/**
128 * Tear down the EGL context currently associated with the display.
129 */
130static void engine_term_display(struct engine* engine) {
131    if (engine->display != EGL_NO_DISPLAY) {
132        eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
133        if (engine->context != EGL_NO_CONTEXT) {
134            eglDestroyContext(engine->display, engine->context);
135        }
136        if (engine->surface != EGL_NO_SURFACE) {
137            eglDestroySurface(engine->display, engine->surface);
138        }
139        eglTerminate(engine->display);
140    }
141    engine->animating = 0;
142    engine->display = EGL_NO_DISPLAY;
143    engine->context = EGL_NO_CONTEXT;
144    engine->surface = EGL_NO_SURFACE;
145}
146  
147/**
148 * Process the next input event.
149 */
150static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
151    struct engine* engine = (struct engine*)app->userData;
152    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
153        engine->animating = 1;
154        engine->state.x = AMotionEvent_getX(event, 0);
155        engine->state.y = AMotionEvent_getY(event, 0);
156        return 1;
157    }
158    return 0;
159}
160  
161/**
162 * Process the next main command.
163 */
164static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
165    struct engine* engine = (struct engine*)app->userData;
166    switch (cmd) {
167        case APP_CMD_SAVE_STATE:
168            // The system has asked us to save our current state.  Do so.
169            engine->app->savedState = malloc(sizeof(struct saved_state));
170            *((struct saved_state*)engine->app->savedState) = engine->state;
171            engine->app->savedStateSize = sizeof(struct saved_state);
172            break;
173        case APP_CMD_INIT_WINDOW:
174            // The window is being shown, get it ready.
175            if (engine->app->window != NULL) {
176                engine_init_display(engine);
177                engine_draw_frame(engine);
178            }
179            break;
180        case APP_CMD_TERM_WINDOW:
181            // The window is being hidden or closed, clean it up.
182            engine_term_display(engine);
183            break;
184        case APP_CMD_GAINED_FOCUS:
185            // When our app gains focus, we start monitoring the accelerometer.
186            if (engine->accelerometerSensor != NULL) {
187                ASensorEventQueue_enableSensor(engine->sensorEventQueue,
188                        engine->accelerometerSensor);
189                // We'd like to get 60 events per second (in us).
190                ASensorEventQueue_setEventRate(engine->sensorEventQueue,
191                        engine->accelerometerSensor, (1000L/60)*1000);
192            }
193            break;
194        case APP_CMD_LOST_FOCUS:
195            // When our app loses focus, we stop monitoring the accelerometer.
196            // This is to avoid consuming battery while not being used.
197            if (engine->accelerometerSensor != NULL) {
198                ASensorEventQueue_disableSensor(engine->sensorEventQueue,
199                        engine->accelerometerSensor);
200            }
201            // Also stop animating.
202            engine->animating = 0;
203            engine_draw_frame(engine);
204            break;
205    }
206}
207  
208/**
209 * This is the main entry point of a native application that is using
210 * android_native_app_glue.  It runs in its own thread, with its own
211 * event loop for receiving input events and doing other things.
212 */
213void android_main(struct android_app* state) {
214    struct engine engine;
215  
216    // Make sure glue isn't stripped.
217    app_dummy();
218  
219    memset(&engine, 0, sizeof(engine));
220    state->userData = &engine;
221    state->onAppCmd = engine_handle_cmd;
222    state->onInputEvent = engine_handle_input;
223    engine.app = state;
224  
225    // Prepare to monitor accelerometer
226    engine.sensorManager = ASensorManager_getInstance();
227    engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
228            ASENSOR_TYPE_ACCELEROMETER);
229    engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
230            state->looper, LOOPER_ID_USER, NULL, NULL);
231  
232    if (state->savedState != NULL) {
233        // We are starting with a previous saved state; restore from it.
234        engine.state = *(struct saved_state*)state->savedState;
235    }
236  
237    // loop waiting for stuff to do.
238  
239    while (1) {
240        // Read all pending events.
241        int ident;
242        int events;
243        struct android_poll_source* source;
244  
245        // If not animating, we will block forever waiting for events.
246        // If animating, we loop until all events are read, then continue
247        // to draw the next frame of animation.
248        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
249                (void**)&source)) >= 0) {
250  
251            // Process this event.
252            if (source != NULL) {
253                source->process(state, source);
254            }
255  
256            // If a sensor has data, process it now.
257            if (ident == LOOPER_ID_USER) {
258                if (engine.accelerometerSensor != NULL) {
259                    ASensorEvent event;
260                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
261                            &event, 1) > 0) {
262                        LOGI("accelerometer: x=%f y=%f z=%f",
263                                event.acceleration.x, event.acceleration.y,
264                                event.acceleration.z);
265                    }
266                }
267            }
268  
269            // Check if we are exiting.
270            if (state->destroyRequested != 0) {
271                engine_term_display(&engine);
272                return;
273            }
274        }
275  
276        if (engine.animating) {
277            // Done with events; draw next animation frame.
278            engine.state.angle += .01f;
279            if (engine.state.angle > 1) {
280                engine.state.angle = 0;
281            }
282  
283            // Drawing is throttled to the screen update rate, so there
284            // is no need to do timing here.
285            engine_draw_frame(&engine);
286        }
287    }
288}


資料來源    http://www.oschina.net/code/snippet_12_2904

沒有留言:

張貼留言