1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4<head> 5<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> 6<meta http-equiv="X-UA-Compatible" content="IE=9"/> 7<meta name="generator" content="Doxygen 1.8.5"/> 8<title>NDK Programmer's Guide: native-activity</title> 9<link href="tabs.css" rel="stylesheet" type="text/css"/> 10<script type="text/javascript" src="jquery.js"></script> 11<script type="text/javascript" src="dynsections.js"></script> 12<link href="navtree.css" rel="stylesheet" type="text/css"/> 13<script type="text/javascript" src="resize.js"></script> 14<script type="text/javascript" src="navtree.js"></script> 15<script type="text/javascript"> 16 $(document).ready(initResizable); 17 $(window).load(resizeHeight); 18</script> 19<link href="doxygen.css" rel="stylesheet" type="text/css" /> 20</head> 21<body> 22<div id="top"><!-- do not remove this div, it is closed by doxygen! --> 23<div id="titlearea"> 24<table cellspacing="0" cellpadding="0"> 25 <tbody> 26 <tr style="height: 56px;"> 27 <td style="padding-left: 0.5em;"> 28 <div id="projectname">NDK Programmer's Guide 29 </div> 30 </td> 31 </tr> 32 </tbody> 33</table> 34</div> 35<!-- end header part --> 36<!-- Generated by Doxygen 1.8.5 --> 37</div><!-- top --> 38<div id="side-nav" class="ui-resizable side-nav-resizable"> 39 <div id="nav-tree"> 40 <div id="nav-tree-contents"> 41 <div id="nav-sync" class="sync"></div> 42 </div> 43 </div> 44 <div id="splitbar" style="-moz-user-select:none;" 45 class="ui-resizable-handle"> 46 </div> 47</div> 48<script type="text/javascript"> 49$(document).ready(function(){initNavTree('md_2__samples_sample--nativeactivity.html','');}); 50</script> 51<div id="doc-content"> 52<div class="header"> 53 <div class="headertitle"> 54<div class="title">native-activity </div> </div> 55</div><!--header--> 56<div class="contents"> 57<div class="textblock"><p>This is a very simple example of a purely native 58application, with no Java source code. In the absence of any Java source, the 59Java compiler still creates an executable stub for the Dalvik Virtual Machine 60("DVM") to run. The stub serves as a wrapper for the actual, native program, 61which lives in the .so file.</p> 62<p>The application itself simply renders a color onto the entire screen, and 63then changes the color partly in response to detected movement.</p> 64<h3>AndroidManifest.xml</h3> 65<p>Make sure not to specify an Android API level lower than 9.</p> 66<pre class="fragment"><uses-sdk android:minSdkVersion="9" /> 67</pre><p>Because this application has only native code, specify 68<code>android:hasCode</code> as <code>false</code>.</p> 69<pre class="fragment"><application android:label="@string/app_name" 70android:hasCode="false"> 71</pre><p>Declare the <code>NativeActivity</code> class.</p> 72<pre class="fragment"> <activity android:name="android.app.NativeActivity" 73</pre><p>For <code>android:value</code>, provide the name of the shared library 74to be built, minus the initial <code>lib</code> and the <code>.so</code> 75extension. This value must be the same as the one you described for 76<code>LOCAL_MODULE</code> in <code>Android.mk</code>.</p> 77<pre class="fragment"> <meta-data android:name="android.app.lib_name" 78 android:value="native-activity" /> 79</pre><h3>Android.mk</h3> 80<p>This file tells the build system the following information:</p> 81<p>The name of the shared library to generate.</p> 82<pre class="fragment">LOCAL_MODULE := native-activity 83</pre><p>The name of the native source-code file.</p> 84<pre class="fragment">LOCAL_SRC_FILES := main.c 85</pre><p>A list of external libraries that will be used in building the binary, 86each preceded by the <code>-l</code> (link-against) option.</p> 87<ul> 88<li>log is a logging library.</li> 89<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> 90section discusses these in more detail.</li> 91<li>EGL, standardized by Khronos, corresponds to the platform-specific portion 92of the graphics API.</li> 93<li>OpenGL ES, the version of OpenGL for Android, depends on EGL.</li> 94</ul> 95<p>Note that, for each library:</p> 96<ul> 97<li>The actual file name starts with <code>lib</code>, and ends with the 98<code>.so</code> extension. For example, the actual file name for the 99<code>log</code> library is <code>liblog.so</code>.</li> 100<li>The library lives in the following directory, relative to the NDK root: 101<code><ndk>/platforms/android-<sdk_version>/arch-<abi>/usr/lib/</code>.</li> 102</ul> 103<pre class="fragment">LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM 104</pre><p>A static library, <code>android_native_app_glue</code>, that the 105application uses to manage <code>NativeActivity</code> lifecycle events, along 106with touch input.</p> 107<pre class="fragment">LOCAL_STATIC_LIBRARIES := android_native_app_glue 108</pre><p>The final line tells the build system to build this static library. 109<code>ndk-build</code> places the built library 110(<code>libandroid_native_app_glue.a</code>) into the <code>obj</code> directory 111generated during the build process. The next sample discusses the 112android_native_app_glue in more detail.</p> 113<pre class="fragment">$(call import-module,android/native_app_glue) 114</pre><p>For more information about the Application.mk file, consult the <a 115href="./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> 116<h3><code>Application.mk</code></h3> 117<p>This line defines the minimum level of Android API Level support.</p> 118<pre class="fragment">APP_PLATFORM := android-10 119</pre><p>Because there is no ABI definition, the build system defaults to 120building only for armeabi.</p> 121<h3>main.c</h3> 122<p>This file essentially contains the entire progam.</p> 123<p>The following includes correspond to the libraries, both shared and static, 124enumerated in <code>Android.mk</code>.</p> 125<pre class="fragment">#include <EGL/egl.h> 126#include <GLES/gl.h> 127 128 129#include <android/sensor.h> 130#include <android/log.h> 131#include <android_native_app_glue> 132</pre><p><code>android_native_app_glue</code> calls the following function, 133passing it a predefined state structure. It also serves as a wrapper that 134simplifies handling of <code>NativeActivity</code> callbacks.</p> 135<pre class="fragment">void android_main(struct android_app* state) { 136</pre><p>Next, the program handles events queued by the glue library. The event 137handler follows the state structure.</p> 138<pre class="fragment">struct engine engine; 139 140 141// Make sure glue isn't stripped by suppressing link-time optimization that 142removes unreferenced code. 143app_dummy(); 144 145 146memset(&engine, 0, sizeof(engine)); 147state->userData = &engine; 148state->onAppCmd = engine_handle_cmd; 149state->onInputEvent = engine_handle_input; 150engine.app = state; 151</pre><p>The application prepares to start monitoring the sensors, using the 152APIs in <code>sensor.h</code>.</p> 153<pre class="fragment"> engine.sensorManager = ASensorManager_getInstance(); 154 engine.accelerometerSensor = 155 ASensorManager_getDefaultSensor(engine.sensorManager, 156 ASENSOR_TYPE_ACCELEROMETER); 157 engine.sensorEventQueue = 158 ASensorManager_createEventQueue(engine.sensorManager, 159 state->looper, LOOPER_ID_USER, NULL, NULL); 160</pre><p>Now, a loop begins, in which the application polls the system for 161messages (sensor events). It sends messages to 162<code>android_native_app_glue</code>, which checks to see whether they match 163any <code>onAppCmd</code> events defined in <code>android_main</code>. When a 164match occurs, the message is sent to the handler for execution.</p> 165<pre class="fragment">while (1) { 166 // Read all pending events. 167 int ident; 168 int events; 169 struct android_poll_source* source; 170 171 172 // If not animating, we will block forever waiting for events. 173 // If animating, we loop until all events are read, then continue 174 // to draw the next frame of animation. 175 while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, 176&events, 177 (void**)&source)) >= 0) { 178 179 180 // Process this event. 181 if (source != NULL) { 182 source->process(state, source); 183 } 184 185 186 // If a sensor has data, process it now. 187 if (ident == LOOPER_ID_USER) { 188 if (engine.accelerometerSensor != NULL) { 189 ASensorEvent event; 190 while (ASensorEventQueue_getEvents(engine.sensorEventQueue, 191 &event, 1) > 0) { 192 LOGI("accelerometer: x=%f y=%f z=%f", 193 event.acceleration.x, event.acceleration.y, 194 event.acceleration.z); 195 } 196 } 197 } 198 199 200 // Check if we are exiting. 201 if (state->destroyRequested != 0) { 202 engine_term_display(&engine); 203 return; 204 } 205 } 206</pre><p>Once the queue is empty, and the program exits the polling loop, the 207program calls OpenGL to draw the screen.</p> 208<pre class="fragment"> if (engine.animating) { 209 // Done with events; draw next animation frame. 210 engine.state.angle += .01f; 211 if (engine.state.angle > 1) { 212 engine.state.angle = 0; 213 } 214 215 216 // Drawing is throttled to the screen update rate, so there 217 // is no need to do timing here. 218 engine_draw_frame(&engine); 219 } 220} </pre> </div></div><!-- contents --> 221</div><!-- doc-content --> 222<!-- start footer part --> 223<div id="nav-path" class="navpath"><!-- id is needed for treeview function! --> 224 <ul> 225 <li class="footer">Generated on Wed Jun 25 2014 00:51:19 for NDK 226Programmer's Guide by 227 <a href="http://www.doxygen.org/index.html"> 228 <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.5 </li> 229 </ul> 230</div> 231</body> 232</html> 233