Home | History | Annotate | Download | only in text
      1 Android NDK Overview
      2 ===
      3 
      4 Introduction:
      5 ---
      6 
      7 The Android NDK is a set of tools that allows Android application developers
      8 to embed native machine code compiled from C and/or C++ source files into
      9 their application packages.
     10 
     11 IMPORTANT:
     12 > The Android NDK can only be used to target Android system images
     13   running Cupcake (a.k.a 1.5) or later versions of the platform.
     14 
     15 > 1.0 and 1.1 system images are specifically *not* supported due to
     16   subtle ABI and toolchain changes that happened for the 1.5 release.
     17 
     18 
     19 I. Android NDK Goals:
     20 ---------------------
     21 
     22 The Android VM allows your application's source code to call methods
     23 implemented in native code through the JNI. In a nutshell, this means that:
     24 
     25   - Your application's source code will declare one or more methods
     26     with the 'native' keyword to indicate that they are implemented through
     27     native code. E.g.:
     28 
     29           native byte[]  loadFile(String  filePath);
     30 
     31   - You must provide a native shared library that contains the
     32     implementation of these methods, which will be packaged into your
     33     application's .apk. This library must be named according to standard
     34     Unix conventions as lib<something>.so, and shall contain a standard JNI
     35     entry point (more on this later). For example:
     36 
     37           libFileLoader.so
     38 
     39   - Your application must explicitly load the library. For example, to load
     40     it at application start-up, simply add the following to its source code:
     41 
     42           static {
     43             System.loadLibrary("FileLoader");
     44           }
     45 
     46     Note that you should not use the 'lib' prefix and '.so' suffix here.
     47 
     48 
     49 The Android NDK is a complement to the Android SDK that helps you to:
     50 
     51   - Generate JNI-compatible shared libraries that can run on the Android
     52     1.5 platform (and later) running on ARM CPUs.
     53 
     54   - Copy the generated shared libraries to a proper location of your
     55     application project path, so they will be automatically added to your
     56     final (and signed) .apks
     57 
     58   - In later revisions of the NDK, we intend to provide tools that help
     59     debug your native code through a remote gdb connection and as much
     60     source/symbol information as possible.
     61 
     62 Moreover, the Android NDK provides:
     63 
     64   - A set of cross-toolchains (compilers, linkers, etc..) that can
     65     generate native ARM binaries on Linux, OS X and Windows (with Cygwin)
     66 
     67   - A set of system headers corresponding to the list of stable native APIs
     68     supported by the Android platform. This corresponds to definitions that
     69     are guaranteed to be supported in all later releases of the platform.
     70 
     71     They are documented in the file docs/STABLE-APIS.html
     72 
     73     IMPORTANT:
     74     Keep in mind that most of the native system libraries in Android system
     75     images are not frozen and might changed drastically, or even deleted,
     76     in later updates and releases of the platform.
     77 
     78   - A build system that allow developers to only write very short build files
     79     to describe which sources need to be compiled, and how. The build system
     80     deals with all the hairy toolchain/platform/CPU/ABI specifics. Moreover,
     81     later updates of the NDK can add support for more toolchains, platforms,
     82     system interfaces without requiring changes in the developer's build
     83     files (more on this later).
     84 
     85 
     86 II. Android NDK Non-Goals:
     87 --------------------------
     88 
     89 The NDK is *not* a good way to write generic native code that runs on Android
     90 devices. In particular, your applications should still be written in the Java
     91 programming language, handle Android system events appropriately to avoid the
     92 "Application Not Responding" dialog or deal with the Android application
     93 life-cycle.
     94 
     95 Note however that is is possible to write a sophisticated application in
     96 native code with a small "application wrapper" used to start/stop it
     97 appropriately.
     98 
     99 A good understanding of JNI is highly recommended, since many operations
    100 in this environment require specific actions from the developers, that are
    101 not necessarily common in typical native code. These include:
    102 
    103   - Not being able to directly access the content of VM objects through
    104     direct native pointers. E.g. you cannot safely get a pointer to a
    105     String object's 16-bit char array to iterate over it in a loop.
    106 
    107   - Requiring explicit reference management when the native code wants to
    108     keep handles to VM objects between JNI calls.
    109 
    110 
    111 The NDK only provides system headers for a very limited set of native
    112 APIs and libraries supported by the Android platform. While a typical
    113 Android system image includes many native shared libraries, these should
    114 be considered an implementation detail that might change drastically between
    115 updates and releases of the platform.
    116 
    117 If an Android system library is not explicitly supported by the NDK
    118 headers, then applications should not depend on it being available, or
    119 they risk breaking after the next over-the-air system update on various
    120 devices.
    121 
    122 Selected system libraries will gradually be added to the set of stable NDK
    123 APIs.
    124 
    125 
    126 III. NDK development in practice:
    127 ---------------------------------
    128 
    129 Here's a very rough overview of how you can develop native code with the
    130 Android NDK:
    131 
    132   1. Place your native sources under `$PROJECT/jni/`...
    133 
    134   2. Write `$PROJECT/jni/Android.mk` to describe your sources
    135      to the NDK build system
    136 
    137   3. Optional: write `$PROJECT/jni/Application.mk` to describe your
    138      project in more details to the build system. You don't need
    139      one to get started though, but this allows you to target
    140      more than one CPU or override compiler/linker flags
    141      (see `docs/APPLICATION-MK.html` for all details).
    142 
    143   4. Build your native code by running "`$NDK/ndk-build`" from your
    144      project directory, or any of its sub-directories.
    145 
    146 The last step will copy, in case of success, the stripped shared libraries
    147 your application needs to your application's root project directory. You
    148 will then need to generate your final .apk through the usual means.
    149 
    150 Now, for a few more details:
    151 
    152 
    153 ### III.1/ Configuring the NDK:
    154 
    155 
    156 Previous releases required that you run the 'build/host-setup.sh'
    157 script to configure your NDK. This step has been removed completely
    158 in release 4 (a.k.a. NDK r4).
    159 
    160 
    161 ### III.2/ Placing C and C++ sources:
    162 
    163 Place your native sources under the following directory:
    164 
    165         $PROJECT/jni/
    166 
    167 Where `$PROJECT` corresponds to the path of your Android application
    168 project.
    169 
    170 You are pretty free to organize the content of 'jni' as you want,
    171 the directory names and structure here will not influence the final
    172 generated application packages, so you don't have to use pseudo-unique
    173 names like `com.<mycompany>.<myproject>` as is the case for application
    174 package names.
    175 
    176 Note that C and C++ sources are supported. The default C++ file extensions
    177 supported by the NDK is '.cpp', but other extensions can be handled as well
    178 (see docs/ANDROID-MK.html for details).
    179 
    180 It is possible to store your sources in a different location by adjusting
    181 your Android.mk file (see below).
    182 
    183 
    184 ### III.3/ Writing an Android.mk build script:
    185 
    186 An Android.mk file is a small build script that you write to describe your
    187 sources to the NDK build system. Its syntax is described in details in
    188 the file docs/ANDROID-MK.html.
    189 
    190 In a nutshell, the NDK groups your sources into "modules", where each module
    191 can be one of the following:
    192 
    193   - a static library
    194   - a shared library
    195 
    196 You can define several modules in a single Android.mk, or you can write
    197 several Android.mk files, each one defining a single module.
    198 
    199 Note that a single Android.mk might be parsed several times by the build
    200 system so don't assume that certain variables are not defined in them.
    201 By default, the NDK will look for the following build script:
    202 
    203         $PROJECT/jni/Android.mk
    204 
    205 If you want to define Android.mk files in sub-directories, you should
    206 include them explicitly in your top-level Android.mk. There is even
    207 a helper function to do that, i.e. use:
    208 
    209         include $(call all-subdir-makefiles)
    210 
    211 This will include all Android.mk files in sub-directories of the current
    212 build file's path.
    213 
    214 
    215 ### III.4/ Writing an Application.mk build file (optional):
    216 
    217 While an Android.mk file describes your modules to the build system, the
    218 Application.mk file describes your application itself. See the
    219 docs/APPLICATION-MK.html document to understand what this file allows you
    220 to do. This includes, among others:
    221 
    222   - The exact list of modules required by your application.
    223 
    224   - The CPU architecture(s) to generate machine code for.
    225 
    226   - Optional information, like whether you want a release or debug
    227     build, specific C or C++ compiler flags and others that should
    228     apply to all modules being built.
    229 
    230 This file is optional: by default the NDK will provide one that simply
    231 builds *all* the modules listed from your Android.mk (and all the makefiles
    232 it includes) and target the default CPU ABI (armeabi).
    233 
    234 There are two ways to use an Application.mk:
    235 
    236   - Place it under `$PROJECT/jni/Application.mk`, and it will be picked
    237     up automatically by the 'ndk-build' script (more on this later)
    238 
    239   - Place it under `$NDK/apps/<name>/Application.mk`, where $NDK
    240     points to your NDK installation path. After that, launch
    241     "`make APP=<name>`" from the NDK directory.
    242 
    243     This was the way this file was used before Android NDK r4.
    244     It is still supported for compatibility reasons, but we strongly
    245     encourage you to use the first method instead, since it is much
    246     simpler and doesn't need modifying / changing directories of the
    247     NDK installation tree.
    248 
    249 Again, see docs/APPLICATION-MK.html for a complete description of its
    250 content.
    251 
    252 
    253 ### III.5/ Invoke the NDK build system:
    254 
    255 The preferred way to build machine code with the NDK is to use the
    256 'ndk-build' script introduced with Android NDK r4. You can also use
    257 a second, legacy, method that depends on creating a '$NDK/apps' subdirectory.
    258 
    259 In both cases, a successful build will copy the final stripped binary modules
    260 (i.e. shared libraries) required by your application to your application's
    261 project path (Note that unstripped versions are kept for debugging
    262 purposes, there is no need to copy unstripped binaries to a device).
    263 
    264 
    265 ### 1: Using the 'ndk-build' command:
    266 
    267 The 'ndk-build' script, located at the top of the NDK installation path
    268 can be invoked directly from your application project directory (i.e. the
    269 one where your AndroidManifest.xml is located) or any of its sub-directories.
    270 For example:
    271 
    272           cd $PROJECT
    273           $NDK/ndk-build
    274 
    275 This will launch the NDK build scripts, which will automatically probe your
    276 development system and application project file to determine what to build.
    277 
    278 For example:
    279 
    280           ndk-build
    281           ndk-build  clean    --> clean generated binaries
    282           ndk-build  -B V=1   --> force complete rebuild, showing commands
    283 
    284 By default, it expects an optional file under $PROJECT/jni/Application.mk,
    285 and a required $PROJECT/jni/Android.mk.
    286 
    287 On success, this will copy the generated binary modules (i.e. shared
    288 libraries) to the appropriate location in your project tree. You can later
    289 rebuild the full Android application package either through the usual
    290 'ant' command, or the ADT Eclipse plug-in.
    291 
    292 See docs/NDK-BUILD.html for a more complete description of what this script
    293 does and which options it can take.
    294 
    295 
    296 ### III.6/ Specifying custom output directories:
    297 
    298 By default, ndk-build places all intermediate generated files under
    299 $PROJECT/obj. You can however select a different location by defining
    300 the NDK_OUT environment variable to point to a different directory.
    301 
    302 When defined, this variable has two effects:
    303 
    304   1. It ensures that all files that normally go under $PROJECT/obj are
    305      stored in $NDK_OUT instead
    306 
    307   2. It tells ndk-gdb to look into $NDK_OUT, instead of $PROJECT/obj for
    308      any symbolized (i.e. unstripped) versions of the generated binaries.
    309 
    310 Similarly you can override the default $PROJECT/libs (for libraries and
    311 gdbserver, etc) by defining NDK_LIBS_OUT to a new path.  This is rarely
    312 done since build system expects the default $PROJECT/libs/
    313 
    314 
    315 ### IV. Rebuild your application package:
    316 
    317 After generating the binaries with the NDK, you need to rebuild your
    318 Android application package files (.apk) using the normal means, i.e.
    319 either using the 'ant' command or the ADT Eclipse plug-in.
    320 
    321 See the Android SDK documentation for more details. The new .apk will
    322 embed your shared libraries, and they will be extracted automatically
    323 at installation time by the system when you install the package on a
    324 target device.
    325 
    326 
    327 ### V. Debugging support:
    328 
    329 The NDK provides a helper script, named 'ndk-gdb' to very easily launch
    330 a native debugging session of your applications.
    331 
    332 Native debugging can *ONLY* be performed on production devices running
    333 Android 2.2 or higher, and does not require root or privileged access, as
    334 long as your application is debuggable.
    335 
    336 For more information, read docs/NDK-GDB.html. In a nutshell, native debugging
    337 follows this simple scheme:
    338 
    339   1. Ensure your application is debuggable (e.g. set android:debuggable
    340      to "true" in your AndroidManifest.xml)
    341 
    342   2. Build your application with 'ndk-build', then install it on your
    343      device/emulator.
    344 
    345   3. Launch your application.
    346 
    347   4. Run 'ndk-gdb' from your application project directory.
    348 
    349 You will get a gdb prompt. See the GDB User Manual for a list of useful
    350 commands.
    351