1Android NDK Overview 2=== 3 4Introduction: 5--- 6 7The Android NDK is a set of tools that allows Android application developers 8to embed native machine code compiled from C and/or C++ source files into 9their application packages. 10 11IMPORTANT: 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 19I. Android NDK Goals: 20--------------------- 21 22The Android VM allows your application's source code to call methods 23implemented 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 49The 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 62Moreover, 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 86II. Android NDK Non-Goals: 87-------------------------- 88 89The NDK is *not* a good way to write generic native code that runs on Android 90devices. In particular, your applications should still be written in the Java 91programming language, handle Android system events appropriately to avoid the 92"Application Not Responding" dialog or deal with the Android application 93life-cycle. 94 95Note however that is is possible to write a sophisticated application in 96native code with a small "application wrapper" used to start/stop it 97appropriately. 98 99A good understanding of JNI is highly recommended, since many operations 100in this environment require specific actions from the developers, that are 101not 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 111The NDK only provides system headers for a very limited set of native 112APIs and libraries supported by the Android platform. While a typical 113Android system image includes many native shared libraries, these should 114be considered an implementation detail that might change drastically between 115updates and releases of the platform. 116 117If an Android system library is not explicitly supported by the NDK 118headers, then applications should not depend on it being available, or 119they risk breaking after the next over-the-air system update on various 120devices. 121 122Selected system libraries will gradually be added to the set of stable NDK 123APIs. 124 125 126III. NDK development in practice: 127--------------------------------- 128 129Here's a very rough overview of how you can develop native code with the 130Android 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 146The last step will copy, in case of success, the stripped shared libraries 147your application needs to your application's root project directory. You 148will then need to generate your final .apk through the usual means. 149 150Now, for a few more details: 151 152 153### III.1/ Configuring the NDK: 154 155 156Previous releases required that you run the 'build/host-setup.sh' 157script to configure your NDK. This step has been removed completely 158in release 4 (a.k.a. NDK r4). 159 160 161### III.2/ Placing C and C++ sources: 162 163Place your native sources under the following directory: 164 165 $PROJECT/jni/ 166 167Where `$PROJECT` corresponds to the path of your Android application 168project. 169 170You are pretty free to organize the content of 'jni' as you want, 171the directory names and structure here will not influence the final 172generated application packages, so you don't have to use pseudo-unique 173names like `com.<mycompany>.<myproject>` as is the case for application 174package names. 175 176Note that C and C++ sources are supported. The default C++ file extensions 177supported by the NDK is '.cpp', but other extensions can be handled as well 178(see docs/ANDROID-MK.html for details). 179 180It is possible to store your sources in a different location by adjusting 181your Android.mk file (see below). 182 183 184### III.3/ Writing an Android.mk build script: 185 186An Android.mk file is a small build script that you write to describe your 187sources to the NDK build system. Its syntax is described in details in 188the file docs/ANDROID-MK.html. 189 190In a nutshell, the NDK groups your sources into "modules", where each module 191can be one of the following: 192 193 - a static library 194 - a shared library 195 196You can define several modules in a single Android.mk, or you can write 197several Android.mk files, each one defining a single module. 198 199Note that a single Android.mk might be parsed several times by the build 200system so don't assume that certain variables are not defined in them. 201By default, the NDK will look for the following build script: 202 203 $PROJECT/jni/Android.mk 204 205If you want to define Android.mk files in sub-directories, you should 206include them explicitly in your top-level Android.mk. There is even 207a helper function to do that, i.e. use: 208 209 include $(call all-subdir-makefiles) 210 211This will include all Android.mk files in sub-directories of the current 212build file's path. 213 214 215### III.4/ Writing an Application.mk build file (optional): 216 217While an Android.mk file describes your modules to the build system, the 218Application.mk file describes your application itself. See the 219docs/APPLICATION-MK.html document to understand what this file allows you 220to 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 230This file is optional: by default the NDK will provide one that simply 231builds *all* the modules listed from your Android.mk (and all the makefiles 232it includes) and target the default CPU ABI (armeabi). 233 234There 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 249Again, see docs/APPLICATION-MK.html for a complete description of its 250content. 251 252 253### III.5/ Invoke the NDK build system: 254 255The 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 257a second, legacy, method that depends on creating a '$NDK/apps' subdirectory. 258 259In 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 261project path (Note that unstripped versions are kept for debugging 262purposes, there is no need to copy unstripped binaries to a device). 263 264 265### 1: Using the 'ndk-build' command: 266 267The 'ndk-build' script, located at the top of the NDK installation path 268can be invoked directly from your application project directory (i.e. the 269one where your AndroidManifest.xml is located) or any of its sub-directories. 270For example: 271 272 cd $PROJECT 273 $NDK/ndk-build 274 275This will launch the NDK build scripts, which will automatically probe your 276development system and application project file to determine what to build. 277 278For example: 279 280 ndk-build 281 ndk-build clean --> clean generated binaries 282 ndk-build -B V=1 --> force complete rebuild, showing commands 283 284By default, it expects an optional file under $PROJECT/jni/Application.mk, 285and a required $PROJECT/jni/Android.mk. 286 287On success, this will copy the generated binary modules (i.e. shared 288libraries) to the appropriate location in your project tree. You can later 289rebuild the full Android application package either through the usual 290'ant' command, or the ADT Eclipse plug-in. 291 292See docs/NDK-BUILD.html for a more complete description of what this script 293does and which options it can take. 294 295 296### III.6/ Specifying custom output directories: 297 298By default, ndk-build places all intermediate generated files under 299$PROJECT/obj. You can however select a different location by defining 300the NDK_OUT environment variable to point to a different directory. 301 302When 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 310Similarly you can override the default $PROJECT/libs (for libraries and 311gdbserver, etc) by defining NDK_LIBS_OUT to a new path. This is rarely 312done since build system expects the default $PROJECT/libs/ 313 314 315### IV. Rebuild your application package: 316 317After generating the binaries with the NDK, you need to rebuild your 318Android application package files (.apk) using the normal means, i.e. 319either using the 'ant' command or the ADT Eclipse plug-in. 320 321See the Android SDK documentation for more details. The new .apk will 322embed your shared libraries, and they will be extracted automatically 323at installation time by the system when you install the package on a 324target device. 325 326 327### V. Debugging support: 328 329The NDK provides a helper script, named 'ndk-gdb' to very easily launch 330a native debugging session of your applications. 331 332Native debugging can *ONLY* be performed on production devices running 333Android 2.2 or higher, and does not require root or privileged access, as 334long as your application is debuggable. 335 336For more information, read docs/NDK-GDB.html. In a nutshell, native debugging 337follows 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 349You will get a gdb prompt. See the GDB User Manual for a list of useful 350commands. 351