NDK Programmer's Guide
Concepts
  • Before Beginning
  • Introduction
  • Process
  • Native Activities and Applications

    Before Beginning

    This guide assumes that you are:

    Introduction

    This section provides a high-level explanation of how the NDK works. The Android NDK is a set of tools allowing you to embed C or C++ (“native code”) into your Android apps. The ability to use native code in Android apps can be particularly useful to developers who wish to do one or more of the following:

    • Port their apps between platforms.
    • Use existing libraries created by other developers (or provide their own libraries to others).
    • Increase performance in certain cases, particularly computationally intensive ones like games.


    Important Notes: The Android NDK can only be used to target Android system images running Android 1.5 (API Level 3) or later. The NDK only provides system headers for a very limited set of native APIs and libraries supported by the Android platform. While a typical Android system image includes many native shared libraries, you should consider them an implementation detail that might change drastically between platform releases. If the NDK headers do not explicitly support an Android system library, then apps should not depend on its being available; otherwise, the next over-the-air (“OTA”) system update may break them.

    Process

    This section introduces the main components used in building a native application for Android, and goes on to describe the flow of building and packaging.

    Main components

    You should have an understanding of the following components, as you build your app:

    • ndk-build: The ndk-build script launches the build scripts at the heart of the NDK. These scripts:
      • Automatically probe your development system and app project file to determine what to build.
      • Generate binaries.
      • Copy the binaries to your app's project path.

    For more information, see the ndk-build section of this guide.

    • Java: From your Java source, the Android build process generates .dex ("Dalvik EXecutable") files, which are what the Android OS runs in the Dalvik Virtual Machine (“DVM”). Even if your app contains no Java source code at all, the build process still generates a .dex executable file within which the native component runs.

    When developing Java components, use the native keyword to indicate methods implemented as native code. For example, the following function declaration tells the compiler that the implementation is in a native library:

    public native int add(int  x, int  y);
    

    • Native shared libraries: The NDK builds these libraries, or .so files, from your native source code.

    Note: If two libraries implement the same method, with the same name, a link error occurs.

    • Native static libraries: The NDK can also build static libraries, or .a files, which you can link against other libraries.

    • Java Native Interface ("JNI"): The JNI is the interface via which the Java and C++ components talk to one another. This guide assumes knowledge of the JNI; for information about it, consult the Java Native Interface Specification.

    • Application Binary Interface ("ABI"): The ABI defines exactly how your app's machine code is expected to interact with the system at runtime. The NDK builds .so files against these definitions. Different ABIs correspond to different architectures: The NDK includes ABI support for ARMEABI (default), MIPS, and x86. For more information, see Supported ABIs.

    • Manifest: If you are writing an app with no Java component to it, you must declare the NativeActivity class in the manifest. The Native Activity section provides more detail on how to do this, under “Using the native-activity.h interface.”

    Note: The following two items only apply in cases in which you are using the toolchains provided with the Android NDK as standalone compilers.

    • Android.mk: You must create an Android.mk configuration file inside your jni folder. The ndk-build script looks at this file, which defines the module and its name, the source files to be compiled, build flags and libraries to link. For more information, see the Android.mk section of this document.

    • Application.mk: You may optionally create an Application.mk file. This file enumerates and describes the modules that your app requires. This information includes:
      • ABIs used to compile for specific platforms.
      • Toolchains.
      • Standard libraries to include (static and dynamic STLport or default system).

    For more information, see the Applicatio n.mk section.

    Flow

    The general flow for developing a native app for Android is as follows:

    1. Design your app, deciding which parts to implement in Java, and which parts to implement as native code.
      Note: While it is possible to completely avoid Java, you are likely to find the Android Java framework useful for tasks including controlling the display and UI.
    2. Create an Android app Project in Eclipse as you would for any other Android project.
    3. If you are writing a native-only app, declare the NativeActivity class in AndroidManifest.xml. You can do so from the Eclipse/ADT Android Manifest Editor, or by hand-editing the file. For more information, see the Native Activity section.
    4. Create an Android.mk file describing the native library, including name, flags, linked libraries and source files to be compiled in the ‘JNI’ directory.
    5. OPTIONAL: Create an Application.mk file configuring the target ABIs, toolchain, release/debug mode, and STL. For any of these that you do not specify, the following default values are used, respectively:
      • ABI: armeabi
      • Toolchain: GCC 4.8
      • Mode: Release
      • STL: system
    6. Place your native source under the project's jni directory.
    7. Use ndk-build to compile the native (.so, .a) libraries.
    8. Build the Java component, producing the executable .dex file.
    9. Package everything into an APK file, containing .so, .dex, and other files needed for your app to run.

    Note that Eclipse can perform steps 7. through 9. in a single operation.

    Native Activities and Applications

    The Android SDK provides a helper class, NativeActivity, that allows you to write a completely native activity. NativeActivity handles the communication between the Android framework and your native code, so you do not have to subclass it or call its methods. All you need to do is declare your application to be native in your AndroidManifest.xml file, and begin creating your native application.

    An Android application using NativeActivity still runs in its own virtual machine, sandboxed from other applications. You can therefore still access Android framework APIs through the JNI. In certain cases, however–such as for sensors, input events, and assets–the NDK provides native interfaces that you can use instead of having to call across the JNI. For more information about such support, see STABLE-APIS.HTML.

    Regardless of whether or not you are developing a native activity, we recommend that you create your projects with the usual Android build tools. Doing so helps ensure building and packaging of Android applications with the correct structure.

    The Android NDK provides you with two choices to implement your native activity:

    • The native_activity.h header defines the native version of the NativeActivity class. It contains the callback interface and data structures that you need to create your native activity. Because the main thread of your application handles the callbacks, your callback implementations must not be blocking. If they block, you might receive ANR (Application Not Responding) errors because your main thread is unresponsive until the callback returns.
    • The android_native_app_glue.h file defines a static helper library built on top of the native_activity.h interface. It spawns another thread, which handles things such as callbacks or input events in an event loop. Moving these events to a separate thread prevents any callbacks from blocking your main thread.

    The <ndk_root>/sources/android/native_app_glue/android_native_app_glue.c source is also available, allowing you to modify the implementation.

    For more information on how to use this static library, examine the native-activity sample application, and its documentation. Further reading is also available in the comments in the <ndk_root>/sources/android/native_app_glue/android_native_app_glue.h file.

    Using the native-activity.h interface

    To implement a native activity with the native-activity.h interface:

    1. Create a jni/ directory in your project's root directory. This directory stores all of your native code.
    2. Declare your native activity in the AndroidManifest.xml file.
    3. Because your application has no Java code, set android:hasCode to false.

              <application android:label="@string/app_name"
      android:hasCode="false">
      

      The android:name attribute of the activity tag must be set to android.app.NativeActivity.

                <activity
      android:name="android.app.NativeActivity"
                  android:label="@string/app_name"
      
      
      Note: You can subclass NativeActivity. If you do, use the name of the subclass instead of NativeActivity.

      The android:value attribute of the meta-data tag specifies the name of the shared library containing the entry point to the application (e.g., C/C++ main), omitting the lib prefix and .so suffix from the library name.

                <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>
      
    4. Create a file for your native activity, and implement the ANativeActivity_onCreate() function, which the app calls when the native activity starts. This function, analogous to main in C/C++, receives a pointer to an ANativeActivity structure, which contains function pointers to the various callback implementations that you need to write. Set the applicable callback function pointers in ANativeActivity->;callbacks to the implementations of your callbacks.
    5. Set the ANativeActivity->;instance field to the address of any instance of specific data that you want to use.
    6. Implement anything else that you want your activity to do upon starting.
    7. Implement the rest of the callbacks that you set in ANativeActivity->;callbacks. For more information on when the callbacks are called, see the SDK documentation for Activity Lifecycles.
    8. Develop the rest of your application.
    9. Create an Android.mk file in the jni/ directory of your project to describe your native module to the build system. For more information, see the Android.mk section.
    10. Once you have an Android.mk file, compile your native code using the ndk-build command.
    11. $ cd <path>/<to>/<project>
      $ <ndk>/ndk-build
      
    12. Build and install your Android project as usual, using Ant or Eclipse. If your native code is in the jni/ directory, the build script automatically packages the .so file(s) built from it into the APK.

    You can find further information on using native-activity.h in the comments in the <ndk_root>/platforms/android-9/arch-arm/usr/include/android/native_a ctivity.h file.