diff options
Diffstat (limited to 'docs/html/ndk/samples')
-rw-r--r-- | docs/html/ndk/samples/index.jd | 26 | ||||
-rw-r--r-- | docs/html/ndk/samples/sample_hellojni.jd | 123 | ||||
-rw-r--r-- | docs/html/ndk/samples/sample_na.jd | 259 | ||||
-rw-r--r-- | docs/html/ndk/samples/sample_teapot.jd | 360 | ||||
-rw-r--r-- | docs/html/ndk/samples/samples_toc.cs | 35 | ||||
-rw-r--r-- | docs/html/ndk/samples/walkthroughs.jd | 13 |
6 files changed, 816 insertions, 0 deletions
diff --git a/docs/html/ndk/samples/index.jd b/docs/html/ndk/samples/index.jd new file mode 100644 index 0000000..6b2cd16 --- /dev/null +++ b/docs/html/ndk/samples/index.jd @@ -0,0 +1,26 @@ +page.title=Samples: Overview +@jd:body + +<p>Welcome to the NDK samples area. Here, you can download a variety of sample +apps to help deepen your understanding the NDK. + + +<p>From this page, you can download samples that provide a look at the NDK in action. A few of the +topics covered are:</p> + +<ul> + <li>Managing your native app's activity lifecycle.</li> + <li>Using native OpenGL on an Android device.</li> + <li>Implementing native audio.</li> + <li>Exporting modules.</li> +</ul> + +<p class="note"><strong>Note: </strong>These samples are also contained in the NDK installation +package; if you have already downloaded the NDK, you have them. They reside in +{@code $NDK/samples/}, where {@code $NDK} is the NDK installation root.</p> + + <div id="sdk-terms-form"> + <p><a href="{@docRoot}shareables/ndk/ndk-samples.zip" class="button"> + Download ndk-samples.zip</a></p> + </div> + diff --git a/docs/html/ndk/samples/sample_hellojni.jd b/docs/html/ndk/samples/sample_hellojni.jd new file mode 100644 index 0000000..fa61b28 --- /dev/null +++ b/docs/html/ndk/samples/sample_hellojni.jd @@ -0,0 +1,123 @@ +page.title=Sample: hello-jni +@jd:body + +<div id="qv-wrapper"> + <div id="qv"> + <h2>On this page</h2> + + <ol> + <li><a href="#an">Android.mk</a></li> + <li><a href="#ap">Application.mk</a></li> + <li><a href="#ji">Java-side Implementation</a></li> + <li><a href="#ci">C-side Implementation</a></li> + </ol> + </li> + </ol> + </div> + </div> + +<p>This sample guides you through HelloJNI, a minimal +application built with the NDK. This sample is in the {@code samples/hello-jni/} directory +under the root directory of your NDK installation.</p> + +<h2 id="an">Android.mk</h2> + +<p>The following two lines provide the name of the native source file, along +with the name of the shared library to build. The full name of the built +library is {@code libhello-jni.so}, once the build system adds the +{@code lib} prefix and the {@code .so} extension.</p> + +<pre class="no-pretty-print"> +LOCAL_SRC_FILES := hello-jni.c +LOCAL_MODULE := hello-jni +</pre> + +<p>For more information about what the {@code Android.mk} file does, and how to use it, see +<a href="{@docRoot}ndk/guides/android_mk.html">Android.mk</a>.</p> + +<h2 id="ap">Application.mk</h2> +<p>This line tells the build system the CPU and architecture against which to build. In this +example, the build system builds for all supported architectures.</p> + +<pre class="no-pretty-print"> +APP_ABI := all +</pre> + +<p>For more information about the {@code Application.mk} file, and how to use it, see +<a href="{@docRoot}ndk/guides/application_mk.html">Application.mk</a>.</p> + +<h2 id="ji">Java-side Implementation</h2> +<p>The {@code helloJNI.java} file is located in {@code hellojni/src/com/example/hellojni/}. It calls +a function to retrieve a string from the native side, then displays it on the screen.</p> + +<p>The source code contains three lines of particular interest to the NDK user. +They are presented here in the order in which they are used, rather than by +line order.</p> + +<p>This function call loads the {@code .so} file upon application startup.</p> + +<pre class="no-pretty-print"> +System.loadLibrary("hello-jni"); +</pre> + +<p>The {@code native} keyword in this method declaration tells the +virtual machine that the function is in the shared library (that is, implemented on the native +side).</p> + +<pre class="no-pretty-print"> +public native String stringFromJNI(); +</pre> + +<p>The Android framework calls the function loaded and declared in the +previous steps, displaying the string on the screen.</p> + +<pre class="no-pretty-print"> +tv.setText( stringFromJNI() ); +</pre> + +<h2 id="ci">C-side Implementation</h2> +<p>The {@code hello-jni.c} file is located in {@code hello-jni/jni/}. It contains a function that +returns a string that <a href="#ji">the Java side requested</a>). The function declaration is as +follows:</p> + +<pre> +jstring +Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, + jobject thiz ) +</pre> + +<p>This declaration corresponds to the native function declared in the +Java source code. The return type, {@code jstring}, is a data type defined +in the +<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html">Java Native +Interface Specification</a>. It is not actually a string, but a +pointer to a Java string.</p> + +<p>After {@code jstring} comes the function name, which is based on the +Java function name and and the path to the file containing it. Construct it +according to the following rules:</p> + +<ul> +<li>Prepend {@code Java_} to it.</li> +<li>Describe the filepath relative to the top-level source directory.</li> +<li>Use underscores in place of forward slashes.</li> +<li>Omit the {@code .java} file extension.</li> +<li>After the last underscore, append the function name.</li> +</ul> + +<p>Following these rules, this example uses the function name +{@code Java_com_example_hellojni_HelloJni_stringFromJNI}. This name refers to a Java +function called {@code stringFromJNI()}, which resides in +{@code hellojni/src/com/example/hellojni/HelloJni.java}.</p> + +<p>{@code JNIEnv*} is the pointer to the VM, and +{@code jobject} is a pointer to the implicit {@code this} object passed from +the Java side.</p> + +<p>The following line calls the VM API {@code (*env)}, and passes it a return value: +that is, the string that the function on the Java side had requested.</p> + +<pre class="no-pretty-print"> +return (*env)->NewStringUTF(env, "Hello from JNI ! +Compiled with ABI " ABI "."); +</pre> diff --git a/docs/html/ndk/samples/sample_na.jd b/docs/html/ndk/samples/sample_na.jd new file mode 100644 index 0000000..a706be5 --- /dev/null +++ b/docs/html/ndk/samples/sample_na.jd @@ -0,0 +1,259 @@ +page.title=Sample: native-activity +@jd:body + +<div id="qv-wrapper"> + <div id="qv"> + <h2>On this page</h2> + + <ol> + <li><a href="#am">AndroidManifest.xml</a></li> + <li><a href="#anm">Android.mk</a></li> + <li><a href="#apm">Application.mk</a></li> + <li><a href="#mac">main.c</a></li> + </ol> + </li> + </ol> + </div> + </div> + +<p>The native-activity sample resides under the NDK installation root, in +{@code samples/native-activity}. It 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 virtual machine to run. +The stub serves as a wrapper for the actual, native program, which is located in the {@code .so} +file.</p> + +<p>The app itself simply renders a color onto the entire screen, and +then changes the color partly in response to movement that it detects.</p> + +<h2 id="am">AndroidManifest.xml</h2> + +<p>An app with only native code must not specify an Android API level lower than 9, which introduced +the <a href="{@docRoot}ndk/guides/concepts.html#naa">{@code NativeActivity}</a> framework class.</p> + +<pre class="no-pretty-print"> +<uses-sdk android:minSdkVersion="9" /> +</pre> + +<p>The following line declares {@code android:hasCode} as {@code false}, as this app has only +native code–no Java. +</p> + +<pre class="no-pretty-print"> +<application android:label="@string/app_name" +android:hasCode="false"> +</pre> + +<p>The next line declares the {@code NativeActivity} class.</p> + +<pre class="no-pretty-print"> +<activity android:name="android.app.NativeActivity" +</pre> + +<p>Finally, the manifest specifies {@code android:value} as the name of the shared library to be +built, minus the initial {@code lib} and the {@code .so} extension. This value must be the same as +the name of {@code LOCAL_MODULE} in {@code Android.mk}.</p> + +<pre class="no-pretty-print"> +<meta-data android:name="android.app.lib_name" + android:value="native-activity" /> +</pre> + +<h2 id="anm">Android.mk</h2> +<p>This file begins by providing the name of the shared library to generate.</p> + +<pre class="no-pretty-print"> +LOCAL_MODULE := native-activity +</pre> + +<p>Next, it declares the name of the native source-code file.</p> + +<pre class="no-pretty-print"> +LOCAL_SRC_FILES := main.c +</pre> + +<p>Next, it lists the external libraries for the build system to use in building the binary. The +{@code -l} (link-against) option precedes each library name.</p> + +<ul> +<li>{@code log} is a logging library.</li> +<li>{@code android} encompasses the standard Android support APIs for NDK. For more information about +the APIs that Android and the NDK support, see <a href="stable_apis.html">Android NDK Native +APIs</a>.</li> +<li>{@code EGL} corresponds to the platform-specific portion of the graphics API.</li> +<li>{@code GLESv1_CM} corresponds to OpenGL ES, the version of OpenGL for Android. This library +depends on EGL.</li> +</ul> + +<p>For each library:</p> + +<ul> +<li>The actual file name starts with {@code lib}, and ends with the +{@code .so} extension. For example, the actual file name for the +{@code log} library is {@code liblog.so}.</li> +<li>The library resides in the following directory, NDK root: +{@code <ndk>/platforms/android-<sdk_version>/arch-<abi>/usr/lib/}.</li> +</ul> + +<pre class="no-pretty-print"> +LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM +</pre> + +<p>The next line provides the name of the static library, {@code android_native_app_glue}, which the +application uses to manage {@code NativeActivity} lifecycle events and touch input.</p> + +<pre class="no-pretty-print"> +LOCAL_STATIC_LIBRARIES := android_native_app_glue +</pre> + +<p>The final line tells the build system to build this static library. +The {@code ndk-build} script places the built library +({@code libandroid_native_app_glue.a}) into the {@code obj} directory +generated during the build process. For more information about the {@code android_native_app_glue} +library, see its {@code android_native_app_glue.h} header and corresponding {@code .c}source file. +</p> + + +<pre class="no-pretty-print"> +$(call import-module,android/native_app_glue) +</pre> + +<p>For more information about the {@code Android.mk} file, see +<a href="{@docRoot}ndk/guides/android_mk.html">Android.mk</a>.</p> + + +<h2 id="apm">Application.mk</h2> + +<p>This line defines the minimum level of Android API Level support.</p> + +<pre class="no-pretty-print"> +APP_PLATFORM := android-10 +</pre> + +<p>Because there is no ABI definition, the build system defaults to building only for +{@code armeabi}.</p> + +<h2 id="mac">main.c</h2> +<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}.</p> + +<pre class="no-pretty-print"> +#include <EGL/egl.h> +#include <GLES/gl.h> + + +#include <android/sensor.h> +#include <android/log.h> +#include <android_native_app_glue> +</pre> + +<p>The {@code android_native_app_glue} library calls the following function, +passing it a predefined state structure. It also serves as a wrapper that +simplifies handling of {@code NativeActivity} callbacks.</p> + +<pre class="no-pretty-print"> +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="no-pretty-print"> +struct engine engine; + + + +// Suppress link-time optimization that removes unreferenced code +// to 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; +</pre> + +<p>The application prepares to start monitoring the sensors, using the +APIs in {@code sensor.h}.</p> + +<pre class="no-pretty-print"> + 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>Next, a loop begins, in which the application polls the system for +messages (sensor events). It sends messages to +{@code android_native_app_glue}, which checks to see whether they match +any {@code onAppCmd} events defined in {@code android_main}. When a +match occurs, the message is sent to the handler for execution.</p> + +<pre class="no-pretty-print"> +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="no-pretty-print"> + 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> diff --git a/docs/html/ndk/samples/sample_teapot.jd b/docs/html/ndk/samples/sample_teapot.jd new file mode 100644 index 0000000..97708a7 --- /dev/null +++ b/docs/html/ndk/samples/sample_teapot.jd @@ -0,0 +1,360 @@ +page.title=Sample: Teapot +@jd:body + +<div id="qv-wrapper"> + <div id="qv"> + <h2>On this page</h2> + + <ol> + <li><a href="#am">AndroidManifest.xml</a></li> + <li><a href="#ap">Application.mk</a></li> + <li><a href="#ji">Java-side Implementation</a></li> + <li><a href="#ni">Native-side Implementation</a></li> + </ol> + </li> + </ol> + </div> + </div> + +<p>The Teapot sample is located under in the {@code samples/Teapot/} directory, under the NDK +installation's root directory. This sample uses the OpenGL library to render the iconic +<a href="http://math.hws.edu/bridgeman/courses/324/s06/doc/opengl.html#basic">Utah +teapot</a>. In particular, it showcases the {@code ndk_helper} helper class, +a collection of native helper functions required for implementing games and +similar applications as native applications. This class provides:</p> + +<ul> +<li>An abstraction layer, {@code GLContext}, that handles certain NDK-specific behaviors.</li> +<li>Helper functions that are useful but not present in the NDK, such as tap detection.</li> +<li>Wrappers for JNI calls for platform features such as texture loading.</li> +</ul> + +<h2 id="am">AndroidManifest.xml</h2> +<p>The activity declaration here is not {@link android.app.NativeActivity} itself, but +a subclass of it: {@code TeapotNativeActivity}.</p> + +<pre class="no-pretty-print"> + <activity android:name="com.sample.teapot.TeapotNativeActivity" + android:label="@string/app_name" + android:configChanges="orientation|keyboardHidden"> +</pre> + +<p>Ultimately, the name of the shared-object file that the build system builds is +{@code libTeapotNativeActivity.so}. The build system adds the {@code lib} prefix and the {@code .so} +extension; neither is part of the value that the manifest originally assigns to +{@code android:value}.</p> + +<pre class="no-pretty-print"> + <meta-data android:name="android.app.lib_name" + android:value="TeapotNativeActivity" /> +</pre> + +<h2 id="ap">Application.mk</h2> +<p>An app that uses the {@link android.app.NativeActivity} framework class must not specify an +Android API level lower than 9, which introduced that class. For more information about the +{@link android.app.NativeActivity} class, see +<a href="{@docRoot}ndk/guides/concepts.html#naa">Native Activities and Applications</a>. +</p> + +<pre class="no-pretty-print"> +APP_PLATFORM := android-9 +</pre> + +<p>The next line tells the build system to build for all supported architectures.</p> +<pre class="no-pretty-print"> +APP_ABI := all +</pre> + +<p>Next, the file tells the build system which +<a href="{@docRoot}ndk/guides/cpp-support.html">C++ runtime support library</a> to use. </p> + +<pre class="no-pretty-print"> +APP_STL := stlport_static +</pre> + +<h2 id="ji">Java-side Implementation</h2> +<p>The {@code TeapotNativeActivity.java} file is located in +{@code samples/Teapot/src/com/sample/teapot}, under the NDK installation root directory. It handles +activity lifecycle events, and also enables the app to display text on the screen. The following +block of code is most important from the perspective of the native-side implementation: The native +code calls it to display a popup window for displaying text.</p> + +<pre class="no-pretty-print"> + +void setImmersiveSticky() { + View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); +} +</pre> + +<h2 id="ni">Native-side Implementation</h2> + +<p>This section explores the part of the Teapot app implemented in C++.</p> + +<h3>TeapotRenderer.h</h3> + +<p>These function calls perform the actual rendering of the teapot. It uses +{@code ndk_helper} for matrix calculation and to reposition the camera +based on where the user taps.</p> + +<pre class="no-pretty-print"> +ndk_helper::Mat4 mat_projection_; +ndk_helper::Mat4 mat_view_; +ndk_helper::Mat4 mat_model_; + + +ndk_helper::TapCamera* camera_; +</pre> + +<h3>TeapotNativeActivity.cpp</h3> + +<p>The following lines include {@code ndk_helper} in the native source file, and define the +helper-class name.</p> + +<pre class="no-pretty-print"> + +#include "NDKHelper.h" + +//------------------------------------------------------------------------- +//Preprocessor +//------------------------------------------------------------------------- +#define HELPER_CLASS_NAME "com/sample/helper/NDKHelper" //Class name of helper +function +</pre> + +<p>The first use of the {@code ndk_helper} class is to handle the +EGL-related lifecycle, associating EGL context states (created/lost) with +Android lifecycle events. The {@code ndk_helper} class enables the application to preserve context +information so that the system can restore a destroyed activity. This ability is useful, for +example, when the target machine is rotated (causing an activity to be +destroyed, then immediately restored in the new orientation), or when the lock +screen appears.</p> + +<pre class="no-pretty-print"> +ndk_helper::GLContext* gl_context_; // handles EGL-related lifecycle. +</pre> + +<p>Next, {@code ndk_helper} provides touch control.</p> + +<pre class="no-pretty-print"> +ndk_helper::DoubletapDetector doubletap_detector_; +ndk_helper::PinchDetector pinch_detector_; +ndk_helper::DragDetector drag_detector_; +ndk_helper::PerfMonitor monitor_; +</pre> + +<p>It also provides camera control (openGL view frustum).</p> + +<pre class="no-pretty-print"> +ndk_helper::TapCamera tap_camera_; +</pre> + +<p>The app then prepares to use the device's sensors, using the native APIs provided in the NDK.</p> + +<pre class="no-pretty-print"> +ASensorManager* sensor_manager_; +const ASensor* accelerometer_sensor_; +ASensorEventQueue* sensor_event_queue_; +</pre> + +<p>The app calls the following functions in response to various Android +lifecycle events and EGL context state changes, using various functionalities +provided by {@code ndk_helper} via the {@code Engine} class.</p> + +<pre class="no-pretty-print"> + +void LoadResources(); +void UnloadResources(); +void DrawFrame(); +void TermDisplay(); +void TrimMemory(); +bool IsReady(); +</pre> + +<p>Then, the following function calls back to the Java side to update the UI display.</p> + +<pre class="no-pretty-print"> +void Engine::ShowUI() +{ + JNIEnv *jni; + app_->activity->vm->AttachCurrentThread( &jni, NULL ); + + + //Default class retrieval + jclass clazz = jni->GetObjectClass( app_->activity->clazz ); + jmethodID methodID = jni->GetMethodID( clazz, "showUI", "()V" ); + jni->CallVoidMethod( app_->activity->clazz, methodID ); + + + app_->activity->vm->DetachCurrentThread(); + return; +} +</pre> + +<p>Next, this function calls back to the Java side to draw a text box +superimposed on the screen rendered on the native side, and showing frame +count.</p> + +<pre class="no-pretty-print"> +void Engine::UpdateFPS( float fFPS ) +{ + JNIEnv *jni; + app_->activity->vm->AttachCurrentThread( &jni, NULL ); + + + //Default class retrieval + jclass clazz = jni->GetObjectClass( app_->activity->clazz ); + jmethodID methodID = jni->GetMethodID( clazz, "updateFPS", "(F)V" ); + jni->CallVoidMethod( app_->activity->clazz, methodID, fFPS ); + + + app_->activity->vm->DetachCurrentThread(); + return; +} +</pre> + +<p>The application gets the system clock and supplies it to the renderer +for time-based animation based on real-time clock. This information is used, for example, in +calculating momentum, where speed declines as a function of time.</p> + +<pre class="no-pretty-print"> +renderer_.Update( monitor_.GetCurrentTime() ); +</pre> + +<p>The application now checks whether the context information that {@code GLcontext} holds is still +valid. If not, {@code ndk-helper} swaps the buffer, reinstantiating the GL context.</p> + +<pre class="no-pretty-print"> +if( EGL_SUCCESS != gl_context_->Swap() ) // swaps +buffer. +</pre> + +<p>The program passes touch-motion events to the gesture detector defined +in the {@code ndk_helper} class. The gesture detector tracks multitouch +gestures, such as pinch-and-drag, and sends a notification when triggered by +any of these events.</p> + +<pre class="no-pretty-print"> + if( AInputEvent_getType( event ) == AINPUT_EVENT_TYPE_MOTION ) + { + ndk_helper::GESTURE_STATE doubleTapState = + eng->doubletap_detector_.Detect( event ); + ndk_helper::GESTURE_STATE dragState = eng->drag_detector_.Detect( event ); + ndk_helper::GESTURE_STATE pinchState = eng->pinch_detector_.Detect( event ); + + //Double tap detector has a priority over other detectors + if( doubleTapState == ndk_helper::GESTURE_STATE_ACTION ) + { + //Detect double tap + eng->tap_camera_.Reset( true ); + } + else + { + //Handle drag state + if( dragState & ndk_helper::GESTURE_STATE_START ) + { + //Otherwise, start dragging + ndk_helper::Vec2 v; + eng->drag_detector_.GetPointer( v ); + eng->TransformPosition( v ); + eng->tap_camera_.BeginDrag( v ); + } + // ...else other possible drag states... + + //Handle pinch state + if( pinchState & ndk_helper::GESTURE_STATE_START ) + { + //Start new pinch + ndk_helper::Vec2 v1; + ndk_helper::Vec2 v2; + eng->pinch_detector_.GetPointers( v1, v2 ); + eng->TransformPosition( v1 ); + eng->TransformPosition( v2 ); + eng->tap_camera_.BeginPinch( v1, v2 ); + } + // ...else other possible pinch states... + } + return 1; + } +</pre> + +<p>The {@code ndk_helper} class also provides access to a vector-math library +({@code vecmath.h}), using it here to transform touch coordinates.</p> + +<pre class="no-pretty-print"> +void Engine::TransformPosition( ndk_helper::Vec2& vec ) +{ + vec = ndk_helper::Vec2( 2.0f, 2.0f ) * vec + / ndk_helper::Vec2( gl_context_->GetScreenWidth(), + gl_context_->GetScreenHeight() ) - ndk_helper::Vec2( 1.f, 1.f ); +} +</pre> +</ul> + +<p>The {@code HandleCmd()} method handles commands posted from the +android_native_app_glue library. For more information about what the messages +mean, refer to the comments in the {@code android_native_app_glue.h} and +{@code .c} source files.</p> + +<pre class="no-pretty-print"> +void Engine::HandleCmd( struct android_app* app, + int32_t cmd ) +{ + Engine* eng = (Engine*) app->userData; + switch( cmd ) + { + case APP_CMD_SAVE_STATE: + break; + case APP_CMD_INIT_WINDOW: + // The window is being shown, get it ready. + if( app->window != NULL ) + { + eng->InitDisplay(); + eng->DrawFrame(); + } + break; + case APP_CMD_TERM_WINDOW: + // The window is being hidden or closed, clean it up. + eng->TermDisplay(); + eng->has_focus_ = false; + break; + case APP_CMD_STOP: + break; + case APP_CMD_GAINED_FOCUS: + eng->ResumeSensors(); + //Start animation + eng->has_focus_ = true; + break; + case APP_CMD_LOST_FOCUS: + eng->SuspendSensors(); + // Also stop animating. + eng->has_focus_ = false; + eng->DrawFrame(); + break; + case APP_CMD_LOW_MEMORY: + //Free up GL resources + eng->TrimMemory(); + break; + } +} +</pre> + +<p>The {@code ndk_helper} class posts {@code APP_CMD_INIT_WINDOW} when {@code android_app_glue} +receives an {@code onNativeWindowCreated()} callback from the system. +Applications can normally perform window initializations, such as EGL +initialization. They do this outside of the activity lifecycle, since the +activity is not yet ready.</p> + +<pre class="no-pretty-print"> + //Init helper functions + ndk_helper::JNIHelper::Init( state->activity, HELPER_CLASS_NAME ); + + state->userData = &g_engine; + state->onAppCmd = Engine::HandleCmd; + state->onInputEvent = Engine::HandleInput; +</pre> diff --git a/docs/html/ndk/samples/samples_toc.cs b/docs/html/ndk/samples/samples_toc.cs new file mode 100644 index 0000000..92266b1 --- /dev/null +++ b/docs/html/ndk/samples/samples_toc.cs @@ -0,0 +1,35 @@ +<?cs # Table of contents for Dev Guide. + + For each document available in translation, add an localized title to this TOC. + Do not add localized title for docs not available in translation. + Below are template spans for adding localized doc titles. Please ensure that + localized titles are added in the language order specified below. +?> + +<ul id="nav"> + + <li class="nav-section"> + <div class="nav-section-header empty"><a href="<?cs var:toroot ?>ndk/samples/index.html"> + <span class="en">Overview</span></a></div> + </li> + + <li class="nav-section"> + <div class="nav-section-header"> + <a href="<?cs var:toroot ?>ndk/samples/walkthroughs.html"> + <span class="en">Walkthroughs</span></a></div> + <ul> + <li><a href="<?cs var:toroot ?>ndk/samples/sample_hellojni.html">hello-jni</a></li> + <li><a href="<?cs var:toroot ?>ndk/samples/sample_na.html">native-activity</a></li> + <li><a href="<?cs var:toroot ?>ndk/samples/sample_teapot.html">Teapot</a></li> + </ul> + </li> +</ul> + + +<script type="text/javascript"> +<!-- + buildToggleLists(); + changeNavLang(getLangPref()); +//--> +</script> + diff --git a/docs/html/ndk/samples/walkthroughs.jd b/docs/html/ndk/samples/walkthroughs.jd new file mode 100644 index 0000000..88ceb56 --- /dev/null +++ b/docs/html/ndk/samples/walkthroughs.jd @@ -0,0 +1,13 @@ +page.title=Samples: Walkthroughs +@jd:body + +<p>This section provides detailed walkthroughs of several key samples. The samples are as +follows:</p> + +<li><a href="{@docRoot}ndk/samples/sample_hellojni.html">hello-jni</a>: A very basic app that +illustrates core workings of the NDK.</li> +<li><a href="{@docRoot}ndk/samples/sample_na.html">native-activity</a>: An app that shows the +fundamentals of constructing a purely native app. It places particular emphasis on the +{@code android_native_app_glue library}.</li> +<li><a href="<a href="{@docRoot}ndk/samples/sample_teapot.html">Teapot</a>: A simple OpenGL demo, +showcasing the <code>ndk_helper</code> class.</li> |