| page.title=Sample: Native Activity |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>On this page</h2> |
| |
| <ol> |
| <li><a href="#bb">Before Beginning</a></li> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#hiw">How It Works</a></li> |
| <li><a href="#naa">Native Activities and Applications</a></li> |
| </ol> |
| </li> |
| </ol> |
| </div> |
| </div> |
| |
| <p>This is a very simple example of a purely native |
| application, with no Java source code. In the absence of any Java source, the |
| Java compiler still creates an executable stub for the Dalvik Virtual Machine |
| ("DVM") to run. The stub serves as a wrapper for the actual, native program, |
| which lives in the .so file.</p> |
| <p>The application itself simply renders a color onto the entire screen, and |
| then changes the color partly in response to detected movement.</p> |
| <h3>AndroidManifest.xml</h3> |
| <p>Make sure not to specify an Android API level lower than 9.</p> |
| <pre class="fragment"><uses-sdk android:minSdkVersion="9" /> |
| </pre><p>Because this application has only native code, specify |
| <code>android:hasCode</code> as <code>false</code>.</p> |
| <pre class="fragment"><application android:label="@string/app_name" |
| android:hasCode="false"> |
| </pre><p>Declare the <code>NativeActivity</code> class.</p> |
| <pre class="fragment"> <activity android:name="android.app.NativeActivity" |
| </pre><p>For <code>android:value</code>, provide the name of the shared library |
| to be built, minus the initial <code>lib</code> and the <code>.so</code> |
| extension. This value must be the same as the one you described for |
| <code>LOCAL_MODULE</code> in <code>Android.mk</code>.</p> |
| <pre class="fragment"> <meta-data android:name="android.app.lib_name" |
| android:value="native-activity" /> |
| </pre><h3>Android.mk</h3> |
| <p>This file tells the build system the following information:</p> |
| <p>The name of the shared library to generate.</p> |
| <pre class="fragment">LOCAL_MODULE := native-activity |
| </pre><p>The name of the native source-code file.</p> |
| <pre class="fragment">LOCAL_SRC_FILES := main.c |
| </pre><p>A list of external libraries that will be used in building the binary, |
| each preceded by the <code>-l</code> (link-against) option.</p> |
| <ul> |
| <li>log is a logging library.</li> |
| <li>android encompasses the standard Android support APIs for NDK. The <a href="./md_3__key__topics__libraries__s_t_a_b_l_e-_a_p_i_s.html">Stable APIs</a> |
| section discusses these in more detail.</li> |
| <li>EGL, standardized by Khronos, corresponds to the platform-specific portion |
| of the graphics API.</li> |
| <li>OpenGL ES, the version of OpenGL for Android, depends on EGL.</li> |
| </ul> |
| <p>Note that, for each library:</p> |
| <ul> |
| <li>The actual file name starts with <code>lib</code>, and ends with the |
| <code>.so</code> extension. For example, the actual file name for the |
| <code>log</code> library is <code>liblog.so</code>.</li> |
| <li>The library lives in the following directory, relative to the NDK root: |
| <code><ndk>/platforms/android-<sdk_version>/arch-<abi>/usr/lib/</code>.</li> |
| </ul> |
| <pre class="fragment">LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM |
| </pre><p>A static library, <code>android_native_app_glue</code>, that the |
| application uses to manage <code>NativeActivity</code> lifecycle events, along |
| with touch input.</p> |
| <pre class="fragment">LOCAL_STATIC_LIBRARIES := android_native_app_glue |
| </pre><p>The final line tells the build system to build this static library. |
| <code>ndk-build</code> places the built library |
| (<code>libandroid_native_app_glue.a</code>) into the <code>obj</code> directory |
| generated during the build process. The next sample discusses the |
| android_native_app_glue in more detail.</p> |
| <pre class="fragment">$(call import-module,android/native_app_glue) |
| </pre><p>For more information about the Application.mk file, consult the <a |
| href="./md_3__key__topics__building__a_p_p_l_i_c_a_t_i_o_n-_m_k.html">Application.mk section</a> of this guide.</p> |
| <h3><code>Application.mk</code></h3> |
| <p>This line defines the minimum level of Android API Level support.</p> |
| <pre class="fragment">APP_PLATFORM := android-10 |
| </pre><p>Because there is no ABI definition, the build system defaults to |
| building only for armeabi.</p> |
| <h3>main.c</h3> |
| <p>This file essentially contains the entire progam.</p> |
| <p>The following includes correspond to the libraries, both shared and static, |
| enumerated in <code>Android.mk</code>.</p> |
| <pre class="fragment">#include <EGL/egl.h> |
| #include <GLES/gl.h> |
| |
| |
| #include <android/sensor.h> |
| #include <android/log.h> |
| #include <android_native_app_glue> |
| </pre><p><code>android_native_app_glue</code> calls the following function, |
| passing it a predefined state structure. It also serves as a wrapper that |
| simplifies handling of <code>NativeActivity</code> callbacks.</p> |
| <pre class="fragment">void android_main(struct android_app* state) { |
| </pre><p>Next, the program handles events queued by the glue library. The event |
| handler follows the state structure.</p> |
| <pre class="fragment">struct engine engine; |
| |
| |
| // Make sure glue isn't stripped by suppressing link-time optimization that |
| removes unreferenced code. |
| app_dummy(); |
| |
| |
| memset(&engine, 0, sizeof(engine)); |
| state->userData = &engine; |
| state->onAppCmd = engine_handle_cmd; |
| state->onInputEvent = engine_handle_input; |
| engine.app = state; |
| </pre><p>The application prepares to start monitoring the sensors, using the |
| APIs in <code>sensor.h</code>.</p> |
| <pre class="fragment"> 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); |
| </pre><p>Now, a loop begins, in which the application polls the system for |
| messages (sensor events). It sends messages to |
| <code>android_native_app_glue</code>, which checks to see whether they match |
| any <code>onAppCmd</code> events defined in <code>android_main</code>. When a |
| match occurs, the message is sent to the handler for execution.</p> |
| <pre class="fragment">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; |
| } |
| } |
| </pre><p>Once the queue is empty, and the program exits the polling loop, the |
| program calls OpenGL to draw the screen.</p> |
| <pre class="fragment"> 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); |
| } |
| } </pre> </div></div><!-- contents --> |
| </div><!-- doc-content --> |
| <!-- start footer part --> |
| <div id="nav-path" class="navpath"><!-- id is needed for treeview function! --> |
| <ul> |
| <li class="footer">Generated on Wed Jun 25 2014 00:51:19 for NDK |
| Programmer's Guide by |
| <a href="http://www.doxygen.org/index.html"> |
| <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.5 </li> |
| </ul> |
| </div> |
| </body> |
| </html> |