Advanced Android: Getting Started with the NDK

Advanced Android: Getting Started with the NDK

Tutorial Details
  • Technology: Android SDK, NDK, C
  • Difficulty: Advanced
  • Estimated Completion Time: 60-90 minutes

Learn how to install the Android NDK and begin using it. By the end of this tutorial, you will have created your own project that makes a simple call from Java code to native C code.

Prerequisite Experience

Before we get started, we need to take a moment here to discuss the level of this tutorial. It’s flagged as advanced. The reason for this is that we, the authors, are going to assume that you would agree with the following statements:

  1. You are experienced with Java and C.
  2. You are comfortable using the command line.
  3. You know how to figure out what version of Cygwin, awk, and other tools you have.
  4. You are comfortable with Android Development.
  5. You have a working Android development environment (as if this writing, the authors are using Android 2.2)
  6. You use Eclipse or can translate Eclipse instructions to your own IDE with ease.

If you aren’t comfortable with these, you’re welcome to read this tutorial, of course, but you may have difficulties at certain steps that would be resolved by being comfortable with the above. That said, using the NDK is still a process that is prone to problems and issues even if you consider yourself a mobile development veteran. Be aware that you may have to do some troubleshooting of your own before you get everything working smoothly on your development system.

The complete sample project for this tutorial can be downloaded open source code.

A Note About When to Use NDK

So, if you’re reading this tutorial, you may already be considering the NDK for your Android projects. However, we’d like to take a moment to talk about why the NDK is important, when it should be used, and—just as importantly, when it should not be used.

Generally speaking, you only need to use the NDK if your application is truly processor bound. That is, you have algorithms that are using all of the processor within the DalvikVM and would benefit from running natively. Also, don’t forget that in Android 2.2, a JIT compiler will improve the performance of such code as well.

Another reason to use the NDK is for ease of porting. If you’ve got loads of C code for your existing application, using the NDK could speed up your project’s development process as well as help keep changes synchronized between your Android and non-Android projects. This can be particularly true of OpenGL ES applications written for other platforms.

Don’t assume you’ll increase your application’s performance just because you’re using native code. The Java<->Native C exchanges add some overhead, so it’s only really worthwhile if you’ve got some intensive processing to do.

Step 0: Downloading the Tools

Alright, let’s get started. You need to download the NDK. We’ll do this first, as while it’s downloading you can check to make sure you have the right versions of the rest of the tools you need.

Download the NDK for your operating system from the Android site.

Now, check the versions of your tools against these:

  1. If on Windows, Cygwin 1.7 or later
  2. Update awk to the most recent version (We’re using 20070501)
  3. GNU Make 3.81 or later (We’re using 3.81)

If any of these versions are too old, please update them before continuing.

Step 1: Installing the NDK

Now that the NDK is downloaded (it is, right?), you need to unzip it. Do so and place it in an appropriate directory. We put ours in the same directory that we put the Android SDK. Remember where you put it.
At this point, you may want to add the NDK tools to your path. If you’re on Mac or Linux, you can do this with your native path setting. If you’re on Windows using Cygwin, you need to configure the Cygwin path setting.

Step 2: Creating the Project

Create a regular Android project. To avoid problems later, your project must reside in a path that contains no spaces. Our project has a package name of “com.mamlambo.sample.ndk1” with a default Activity name of “AndroidNDK1SampleActivity” – you’ll see these appear again soon.

At the top level of this project, create a directory called “jni” – this is where you’ll put your native code. If you’re familiar with JNI, the Android NDK is heavily based on JNI concepts – it is, essentially, JNI with a limited set of headers for C compilation.

Step 3: Adding Some C Code

Now, within the jni folder, create a file called native.c. Place the following C code in this file to start; we’ll add another function later:

#include <jni.h>
#include <string.h>
#include <android/log.h>
#define DEBUG_TAG "NDK_AndroidNDK1SampleActivity"
void Java_com_mamlambo_sample_ndk1_AndroidNDK1SampleActivity_helloLog(JNIEnv * env, jobject this, jstring logThis)
{
    jboolean isCopy;
    const char * szLogThis = (*env)->GetStringUTFChars(env, logThis, &isCopy);
    __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:LC: [%s]", szLogThis);
    (*env)->ReleaseStringUTFChars(env, logThis, szLogThis);
}

This function is actually fairly straightforward. It takes in a Java object String parameter, converts it in to a C-string, and then writes it out to LogCat.

The name of the function, though, is important. It follows the specific pattern of “Java,” followed by the package name, followed by the class name, followed by the method name, as defined from Java. Every piece is separated by an underscore instead of a dot.

The first two parameters of the function are critical, too. The first parameter is the JNI environment, frequently used with helper functions. The second parameter is the Java object that this function is a part of.

Step 4: Calling Native From Java

Now that you have written the native code, let’s switch back over to Java. In the default Activity, create a button and add a button handler however you want. From within your button handler, make the call to helloLog:

helloLog("This will log to LogCat via the native call.");

Then you have to add the function declaration on the Java side. Add the following declaration to your Activity class:

private native void helloLog(String logThis);

This tells the compilation and linking system that the implementation for this method will be from the native code.

Finally, you need to load the library that the native code will ultimately compile to. Add the following static initializer to the Activity class to load the library by name (the library name itself is up to you, and will be referenced again in the next step):

static {
    System.loadLibrary("ndk1");
}

Step 5: Adding the Native Code Make File

Within the jni folder, you now need to add the makefile that will be used during compilation. This file must be named “Android.mk” and if you named your file native.c and your library ndk1, then the Android.mk contents will look like this:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE    := ndk1
LOCAL_SRC_FILES := native.c
include $(BUILD_SHARED_LIBRARY)

Step 6: Compiling the Native Code

Now that your native code is written and your make file is in place, it’s time to compile the native code. From the command line (Windows users, you’ll want to do this within Cygwin), you’ll need to run the ndk-build command from the root directory of your project. The ndk-build tool is found within the NDK tools directory. We find it easiest to add this tool to our path.

Fig 1: Typical build output from the ndk-build command

On subsequent compiles, you can make sure everything is recompiled if you use the “ndk-build clean” command.

Step 7: Running the Code

Now you’re all set to run the code. Load the project in to your favorite emulator or handset, watch LogCat, and push the button.

One of two things may have happened. First, it may have worked. If so, congratulations! But you might want to read on, anyway. You probably got an error to LogCat saying something like, “Could not execute method of activity.” This is fine. It just means you missed a step. This is easy to do in Eclipse. Usually, Eclipse is configured to recompile automatically. What it doesn’t do is recompile and relink automatically if it doesn’t know anything has changed. And, in this case, what Eclipse doesn’t know is that you compiled the native code. So, force Eclipse to recompile by “cleaning” the project (Project->Clean from the Eclipse toolbar).

Step 8: Adding Another Native Function

This next function will demonstrate the ability to not only return values, but to return an object, such as a String. Add the following function to native.c:

jstring Java_com_mamlambo_sample_ndk1_AndroidNDK1SampleActivity_getString(JNIEnv * env, jobject this, jint value1, jint value2)
{
    char *szFormat = "The sum of the two numbers is: %i";
    char *szResult;
    // add the two values
    jlong sum = value1+value2;
    // malloc room for the resulting string
    szResult = malloc(sizeof(szFormat) + 20);
    // standard sprintf
    sprintf(szResult, szFormat, sum);
    // get an object string
    jstring result = (*env)->NewStringUTF(env, szResult);
    // cleanup
    free(szResult);
    return result;
}

For this to compile, you’ll want to add an include statement as well for stdio.h. And, to correspond to this new native function, add the following declaration in your Activity Java class:

private native String getString(int value1, int value2);

You can now wire up the functionality however you like. We used the following two calls and outputs:

String result = getString(5,2);
Log.v(DEBUG_TAG, "Result: "+result);
result = getString(105, 1232);
Log.v(DEBUG_TAG, "Result2: "+result);

Back to the C function, you’ll note that we did a couple things. First, we create need a buffer to write to for the sprintf() call using the malloc() function. This is reasonable so long as you don’t forget to free the results when you’re done using the free() function. Then, to pass the result back, you can use a JNI helper function called NewStringUTF(). This function basically it takes the C string and makes a new Java object out of it. This new String object can then be returned as the result and you’ll be able to use it as a regular Java String object from the Java class.

Fig 2: Screen from sample implementation

Instruction Sets, Compatibility, Etc.

The Android NDK requires Android SDK 1.5 or later. In later versions of the NDK, new headers have been made available for expanded access to certain APIs—in particular, OpenGL ES libraries.

However, that’s not the compatibility we’re talking about. This is native code, compiled to the processor architecture in use. So, one question you might be asking yourself is what processor architectures are supported? In the current NDK (as of this writing) only the ARMv5TE and ARMv7-A instruction sets are supported. By default, the target is set to ARMv5TE, which will work on all Android devices with ARM chips.

There are plans for further instruction sets (x86 has been mentioned). This has an interesting implication: an NDK solution will not work on all devices. For instance, there are Android tablets out there that use the Intel Atom processor, which has an x86 instruction set.

So how does the NDK work on the emulator? The emulator is running a true virtual machine, including full processor emulation. And yes, that means when running Java within the emulator you’re running a VM inside a VM.

Conclusion

How did you do? Did you get Android NDK installed and ultimately make a functional, running application that uses native C code as part of it? We hope so. There are many potential “gotchas!” along the way but in some cases, it can be worth the effort. As always, we’d love to hear your feedback.

About the Authors

Mobile developers Lauren Darcey and Shane Conder have coauthored several books on Android development: an in-depth programming book entitled Android Wireless Application Development and Sams TeachYourself Android Application Development in 24 Hours. When not writing, they spend their time developing mobile software at their company and providing consulting services. They can be reached at via email to androidwirelessdev+mt@gmail.com, via their blog at androidbook.blogspot.com, and on Twitter @androidwireless.

Need More Help Writing Android Apps? Check out our Latest Books and Resources!

Buy Android Wireless Application Development, 2nd Edition  Buy Sam's Teach Yourself Android Application Development in 24 Hours  Mamlambo code at Code Canyon

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Ian Rodriguez

    Excellent work!!!

    Very nice tut, been trying to find something about the NDK.

    Cheers!!!!!

  • http://ramblingwood.com Alec Gorge

    Whoa. That’s a long function name.

    • http://androidbook.blogspot.com/ Shane Conder & Lauren Darcey
      Author

      Yeah; the function names can get out of hand quickly if you’re working under a relatively deep Java package hierarchy. Good thing for assisted typing in modern IDEs, huh?

  • Jasperdc

    I’m really wondering why it is taking so long before some decent games are ported to Android like what is happening on the Palm WebOS environment… many of those games really look AMAZING! Even EA games managed to port some pretty high-end games to that platform.

    But still nothing on Android… which is really disappointing to be honest.

    • http://androidbook.blogspot.com/ Shane Conder & Lauren Darcey
      Author

      There are many great games on Android, even from big name publishers. Finding them, though, seems to be the problem.

      But, games like Asphalt HD, Call of Duty, Guitar Hero, and so on look like they should be every bit as good as their iPhone counterparts. Even EA has Android game(s).

      Oddly, some game companies — such as Gameloft — provide some of their games only as direct purchases from their own website and *not* via the Android Market. That won’t help the perception about good games being on the Market.

      • Coop

        If porting game engine is this easy, there would have many iphone games porting to android.

        Be real

  • Ryan

    I guess I fail prerequisite #4, as I’m new to Android development. Not sure how to “In the default Activity, create a button and add a button handler however you want.” Could someone make some source code available that shows this? Otherwise super tutorial!!

    • vinay

      add this code to xml file

      add ” Button btn;” code in ur java file above @overide and inside “oncreate” class paste the following code

      btn=(Button)findViewById(R.id.Button01);

      btn.setOnClickListener(new View.OnClickListener() {

      @Override
      public void onClick(View v) {
      //your action…

      }
      });

      i hope it helpful:)

      • keifer

        I do not know anything about this field, so I have one question, How to run after successfully compile? =P

      • Vinay

        Learn to use android SDK before learning NDK buddy..

  • http://none Michael

    Hi,
    Thanks for the tutorial.
    I tried following on it but I always get the following error message :
    make: *** No rule to make target `/native.c’
    I have Eclipse 3.6 , latest cygwin and latest ndk package for Windows.

    What am I doing wrong?

    • Andy

      Michael, I’m running into the same problem as you, any chance you have figured it out?

  • Slawek

    Hi,

    I’ve got the same issue like Michael. Could you help us?

    Best regards

    • Andy

      Slawek,

      I’m running into the same problem as you, any chance you’ve figured it out?

  • Nick

    Here’s a shortcut to an Android.mk that will work…

    # Within the jni folder, you now need to add the makefile that will be used during compilation.
    # This file must be named “Android.mk” and if you named your file native.c and your library ndk1,
    # then the Android.mk contents will look like this:

    # LOCAL_PATH := $(call my-dir)
    LOCAL_PATH := ./jni

    include $(CLEAR_VARS)

    LOCAL_LDLIBS := -llog
    LOCAL_MODULE := ndk1
    LOCAL_SRC_FILES := native.c
    include $(BUILD_SHARED_LIBRARY)

    # Now that your native code is written and your make file is in place,
    # it’s time to compile the native code. From the command line
    # you’ll need to run the ndk-build command from the root directory of your project.
    # The ndk-build tool is found within the NDK tools directory.
    # We find it easiest to add this tool to our path.

    # Todo: add this to make external tools to be done with it…
    # For now: go to root of project and run ndk-build or ndk-build clean

  • ntg

    Actually, found out what was wrong with Android.mk after all:
    delete all leading and following spaces from

    LOCAL_PATH := $(call my-dir)
    ^^^^delete these spaces….

  • ntg

    Actually, found out what was wrong with Android.mk after all:
    delete all leading and following spaces from

    LOCAL_PATH := $(call my-dir)
    ^————————————-^^^^delete these spaces…

    Nick

    • LxZv

      I Tried but, doesn work, then I delete ALL the spaces something like this:

      LOCAL_PATH:=$(call my-dir)<– No spaces here
      include $(CLEAR_VARS)<– No spaces here
      LOCAL_LDLIBS:=-llog<– No spaces here
      LOCAL_MODULE:=ndk1<– No spaces here
      LOCAL_SRC_FILES:=native.c<– No spaces here
      include $(BUILD_SHARED_LIBRARY)<– No spaces here
      <– No spaces here

      And it works :)

  • Charles Maxwell

    I have built an Android application using shared libraries using the NDK. The emulator is currently running on a Linux x86 platform. However, I now need to move libraries over to an ARM processor. I also would like to use a cross compiler specific for the device’s platform that also handles C++ better. Everything I’ve read so far is rather cryptic.

    1) How do I change to a new platform?
    2) How do I change to use an existing cross-compiler?

    • http://androidbook.blogspot.com/ Shane Conder & Lauren Darcey
      Author

      The emulator is emulating the Android environment. Applications running within it, even NDK ones, still run within the Dalvik virtual machine. The NDK portions use JNI to pass down to a lower layer. The emulator at this level is emulating the ARM code.

      As such, the code you’re compiling and running will work on the emulator as well as actual hardware devices. The fact that the emulator is running on an x86 Linux machine isn’t relevant.

      Another possible interpretation of your question is that you’re asking how to port the libraries over from Linux to Android on ARM. You’ll first need the source code for them. Then you’ll need to include them as you would other libraries within your Android build environment. The details of this are highly dependent on exactly what you’re building (and is thus well beyond the realm of a generic answer ;) ).

  • Abraham

    Awesome Tutorial, thanks for sharing sir!!!

  • mpla

    wtf? I haven’t seen any c-code like that? And they call that native? LOL

  • immibis

    sizeof(szFormat) should really be strlen(szFormat), since the size of the pointer is probably 4, even though the string is much longer.

  • DietCokeOfEvil

    Great post, this really helped me get up and running.

  • http://twitter.com/divyekapoor Divye Kapoor

    There’s a bug in your native code:
    You incorrectly size the buffer szResult to be of size 24/28 bytes leading to a potential buffer overflow in your call to sprintf(szResult, szFormat, sum);

    In the code:

    // malloc room for the resulting string
    szResult = malloc(sizeof(szFormat) + 20);

    the size of the char array allocated to szResult is 24 bytes as sizeof(szFormat) == 4 or 8 as szFormat is of type char* (which is 4 bytes on a 32 bit machine and 8 bytes on a 64 bit machine). The results would have been different if you had initialized szFormat as char[] szFormat = “…”; where upon sizeof(szFormat) would have given you the size of the format string in bytes.

    Please fix.

    Thanks.

  • Kiet

    Thank you. Your demo is short and precise. I was able to pass data from C to Java. Just missing the add button as Vinay pointed out.
    Kiet

  • Anand

    Hi,

    I want to write JNI for existing c code, I have c code and header, i
    created the .so file using cygwin, I wrote the Android.mk file and
    using cygwin created the shared library first it was showing
    “undefined reference to function name” error, then I removed “include $
    (CLEAR_VARS)” and again run the ndk-build command then shared library
    was created but while running it was showing UnsatisfiedLinker
    Error.my make file is
    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE := test
    LOCAL_SRC_FILES := libtest.so

    include $(PREBUILT_SHARED_LIBRARY)

    #LOCAL_PATH := $(call my-dir)

    #include $(CLEAR_VARS)

    LOCAL_C_INCLUDES := $(LOCAL_PATH)

    LOCAL_MODULE := jni_anand
    LOCAL_CPP_EXTENSION := .cpp
    LOCAL_SRC_FILES := anand.cpp
    LOCAL_SHARED_LIBRARY := test

    include $(BUILD_SHARED_LIBRARY)

    Thanks…

  • Abraham

    Awesome, thanks a lot.

  • Martin

    Really nice guide, thank you for that!

    I have however a suggestion to improvement, you could mention that it is very important not to have any non intended spaces in the Android.mk

    When I copied your Android.mk from the site two whitespaces was inserted after LOCAL_PATH := (call my-dir) this gave me an unfriendly error and it was hard figuring out the cause, as always uncle internet saved my day.

    This might however help others.

    Thanks for a superb guide!
    Martin.

  • krish

    nice tutorials..pls send me simple login form using android native apps

  • http://epikfail.tistory.com Hwang

    Thx from korea!

    I love your posts.

  • Kike

    Excellent post!!
    I had some trouble building in VM (virtual box – android x86). But I resolved by adding a file “Application.mk” in the “jni” folder with the line:

    APP_ABI: = x86

    Greetings (from the third world). Kike.

  • fangstar

    Nice Guide.

    Had a trouble with the extra spaces in the makefile but otherwise perfect.

  • aj_shehan

    The android developer site tells that using NDK does not improve the application performance since it runs on JVM nayway, is this true? are there any improvements in performance when using NDK in application practically? I read on a blog which also provides a tutorial on a basic app that uses NDK and it said that it does improve performance. Can you please clarify this for me.

    Than You

  • amit

    nice tutorial!

    i am in home directory of the project and then i tried running ndk-build
    it was working for me earlier but now it gives
    ndk-build

    Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: /Users/naveenkumar/workspace/com.gslab.zap:/Users/naveenkumar/Android/android-ndk-r8:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/naveenkumar/Android/android-ndk-r8:/usr/X11/bin:/usr/local/git/bin/jni/Android.mk

    i got that the path is not the one given here but it has to be /Users/naveenkumar/Documents/workspace/JniHello/jni/Android.mk
    where my Android.mk is present but i dont kw how to change APP_BUILD_SCRIPT to point to this location

    help me out thanks in advance

  • amit

    NAVEEN-KUMARs-MacBook-Pro:ndkfoo naveenkumar$ ls
    AndroidManifest.xml bin jni obj project.properties src
    assets gen libs proguard.cfg res
    NAVEEN-KUMARs-MacBook-Pro:ndkfoo naveenkumar$ /Users/naveenkumar/Downloads/android-ndk-r8/ndk-build NDK_LOG=1
    HOST_OS=darwin
    HOST_ARCH=x86_64
    HOST_TAG=darwin-x86 (no 64-bit prebuilt binaries detected)
    GNUMAKE=/Users/naveenkumar/Downloads/android-ndk-r8/prebuilt/darwin-x86/bin/make (NDK prebuilt)
    Android NDK: NDK installation path auto-detected: ‘/Users/naveenkumar/Downloads/android-ndk-r8′
    Android NDK: GNU Make version 3.81 detected
    Android NDK: Host OS was auto-detected: darwin
    Android NDK: Host operating system detected: darwin
    Android NDK: Host CPU was auto-detected: x86
    Android NDK: HOST_TAG set to darwin-x86
    Android NDK: Host tools prebuilt directory: /Users/naveenkumar/Downloads/android-ndk-r8/prebuilt/darwin-x86/bin
    Android NDK: Host ‘echo’ tool: echo
    Android NDK: Host ‘awk’ tool: /Users/naveenkumar/Downloads/android-ndk-r8/prebuilt/darwin-x86/bin/awk
    Android NDK: Host ‘awk’ test returned: Pass
    Android NDK: This NDK supports the following target architectures and ABIS:
    Android NDK: arm: armeabi armeabi-v7a
    Android NDK: mips: mips
    Android NDK: x86: x86
    Android NDK: This NDK supports the following toolchains and target ABIs:
    Android NDK: arm-linux-androideabi-4.4.3: armeabi armeabi-v7a
    Android NDK: mipsel-linux-android-4.4.3: mips
    Android NDK: x86-4.4.3: x86
    Android NDK: Found platform root directory: /Users/naveenkumar/Downloads/android-ndk-r8/platforms
    Android NDK: Found supported platforms: android-14 android-3 android-4 android-5 android-8 android-9
    Android NDK: PLATFORM android-14 supports: arm mips x86
    Android NDK: ABI arm sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-14/arch-arm
    Android NDK: ABI mips sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-14/arch-mips
    Android NDK: ABI x86 sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-14/arch-x86
    Android NDK: PLATFORM android-3 supports: arm mips x86
    Android NDK: ABI arm sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-3/arch-arm
    Android NDK: ABI mips sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-3/arch-mips
    Android NDK: ABI x86 sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-3/arch-x86
    Android NDK: PLATFORM android-4 supports: arm mips x86
    Android NDK: ABI arm sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-4/arch-arm
    Android NDK: ABI mips sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-4/arch-mips
    Android NDK: ABI x86 sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-4/arch-x86
    Android NDK: PLATFORM android-5 supports: arm mips x86
    Android NDK: ABI arm sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-5/arch-arm
    Android NDK: ABI mips sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-5/arch-mips
    Android NDK: ABI x86 sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-5/arch-x86
    Android NDK: PLATFORM android-8 supports: arm mips x86
    Android NDK: ABI arm sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-8/arch-arm
    Android NDK: ABI mips sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-8/arch-mips
    Android NDK: ABI x86 sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-8/arch-x86
    Android NDK: PLATFORM android-9 supports: arm mips x86
    Android NDK: ABI arm sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-9/arch-arm
    Android NDK: ABI mips sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-9/arch-mips
    Android NDK: ABI x86 sysroot is: /Users/naveenkumar/Downloads/android-ndk-r8/platforms/android-9/arch-x86
    Android NDK: Found stable platform levels: 14 3 4 5 8 9
    Android NDK: Found max platform level: 14
    Android NDK: Found project path: /Users/naveenkumar/workspace/com.gslab.zap:/Users/naveenkumar/Android/android-ndk-r8:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/naveenkumar/Android/android-ndk-r8:/usr/X11/bin:/usr/local/git/bin
    Android NDK: Ouput path: /Users/naveenkumar/workspace/com.gslab.zap:/Users/naveenkumar/Android/android-ndk-r8:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/naveenkumar/Android/android-ndk-r8:/usr/X11/bin:/usr/local/git/bin/obj
    Android NDK: Parsing /Users/naveenkumar/Downloads/android-ndk-r8/build/core/default-application.mk
    Android NDK: Defaulted to APP_PLATFORM=android-3
    Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: /Users/naveenkumar/workspace/com.gslab.zap:/Users/naveenkumar/Android/android-ndk-r8:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/naveenkumar/Android/android-ndk-r8:/usr/X11/bin:/usr/local/git/bin/jni/Android.mk
    /Users/naveenkumar/Downloads/android-ndk-r8/build/core/add-application.mk:133: *** Android NDK: Aborting… . Stop.

    this is the complete output that i am getting and i m inside the root of the project but somehow it is finding the wrong project path dont kw wats wrong ,,, :(

  • Aneesv

    Is there any way to build android source into apk using php code ?

  • Andrew

    Hey, I’m trying to run the ndk-build from Cygwin. I know this question is very stupid, but I cannot reach the project root directory. If I do cd .., it brings me to the Cygwin home folder. I need to go back three more folders, then go into my workspace. Am I doing something wrong? I feel like there needs to be a simple fix…

    • Jimmy

      Change the Path variables in your bash_profile file within the cygwin/home directory

  • Jim

    Hey, I’m not stuck just yet, but have a question to ask. When you say “Add the NDK Tools to my path,” what directory within the NDK folder am I added to the PATH variable? I’m not familiar with Environment Variables and not too sure how they work.

    • Jimmy

      The NDK folder itself…

  • Jimmy

    Hey,
    In your example you say to call the native function, put the following in the default Activity. I currently have a program with multiple files written in C, and multiple Activities. Each Activity needs to call different methods from a few different C files. Is there any sort of declaration that tells the Activity where to look for the correct native methods, or does it just search the JNI folder on its own and find them?
    Thanks,
    Jimmy

  • Andy

    Hey guys,

    I had a general question about using the NDK. Do I need to put the native code information in an Activity, or can it just be used in a regular class?

    static {
    System.loadLibrary(“ndk1″);
    }

    private native void helloLog(String logThis);

    This is the code I am talking about. I would also like to make the methods static, so that every Activity I have can access them. Do you know if this is possible?

  • dhaneesh

    Good guide but ,when I am trying to compile the native.c using ndk-build it shows:

    ndk-build : commnad not found

    what is the reason behing problem?

  • http://pfebriana81.wordpress.com putria febriana

    c:/dev/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld.exe: BFD (GNU Binutils) 2.21 assertion fail /usr/local/google/home/andrewhsieh/ndk-andrewhsieh/src/build/../binutils/binutils-2.21/bfd/elf32-arm.c:10190
    c:/dev/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld.exe: BFD (GNU Binutils) 2.21 assertion fail /usr/local/google/home/andrewhsieh/ndk-andrewhsieh/src/build/../binutils/binutils-2.21/bfd/elf32-arm.c:10190
    Install : libnative_sample.so => libs/armeabi-v7a/libnative_sample.so
    c:/dev/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld.exe: BFD (GNU Binutils) 2.21 assertion fail /usr/local/google/home/andrewhsieh/ndk-andrewhsieh/src/build/../binutils/binutils-2.21/bfd/elf32-arm.c:10190

    c:/dev/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld.exe: BFD (GNU Binutils) 2.21 assertion fail /usr/local/google/home/andrewhsieh/ndk-andrewhsieh/src/build/../binutils/binutils-2.21/bfd/elf32-arm.c:10190

  • Dhaval

    Hello guys an Update, no need of cywin for windows now. NDK directly handles that stuff

    • Amrut Bidri

      Hi Dhaval, i need to know how does it do that. i want to know how eclipse comes that it is using ndk.

  • Ian

    But for development using cocos2dX cygwin is required.

  • Sohel

    Nice Post.
    Thanks

  • shr

    If you are getting an error “make: No rule to make target” , make sure there is no space in the end of the first line of Android.mk.

  • makar

    I cannot understand what include paths to use if I want to, for instance, use the ndk’s version of string

  • http://www.facebook.com/people/Frank-Høvin/556876875 Frank Høvin

    I’ve copied the EXACT same names for the files, project etc. Stil, when running your exact code, I get:

    jni/native.c:1:17: warning: extra tokens at end of #include directive [enabled by default]
    jni/native.c:2:20: warning: extra tokens at end of #include directive [enabled by default]
    jni/native.c:3:25: warning: extra tokens at end of #include directive [enabled by default]
    jni/native.c: In function ‘Java_com_mamlambo_sample_ndk1_AndroidNDK1SampleActivity_helloLog’:
    jni/native.c:8:38: error: ‘gt’ undeclared (first use in this function)
    jni/native.c:8:38: note: each undeclared identifier is reported only once for each function it appears in
    jni/native.c:8:74: error: ‘amp’ undeclared (first use in this function)
    jni/native.c:8:77: error: expected ‘)’ before ‘;’ token
    /cygdrive/c/android-ndk-r8c/build/core/build-binary.mk:260: recipe for target `obj/local/armeabi/objs/ndk1/native.o’ failed
    make: *** [obj/local/armeabi/objs/ndk1/native.o] Error 1
    jni/native.c:1:17: warning: extra tokens at end of #include directive [enabled by default]
    jni/native.c:2:20: warning: extra tokens at end of #include directive [enabled by default]
    jni/native.c:3:25: warning: extra tokens at end of #include directive [enabled by default]
    jni/native.c: In function ‘Java_com_mamlambo_sample_ndk1_AndroidNDK1SampleActivity_helloLog’:
    jni/native.c:8:38: error: ‘gt’ undeclared (first use in this function)
    jni/native.c:8:38: note: each undeclared identifier is reported only once for each function it appears in
    jni/native.c:8:74: error: ‘amp’ undeclared (first use in this function)
    jni/native.c:8:77: error: expected ‘)’ before ‘;’ token
    /cygdrive/c/android-ndk-r8c/build/core/build-binary.mk:260: recipe for target `obj/local/armeabi/objs/ndk1/native.o’ failed
    make: *** [obj/local/armeabi/objs/ndk1/native.o] Error 1

    Seems you’re using html entities in the c function?

    Also, since NDK is now supposed to be able to do this without Cygwin, I tried building and running the application directly from Exlipse, with this result:

    12-10 11:15:20.593: W/dalvikvm(472): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/mamlambo/sample/ndk1/AndroidNDK1SampleActivity;
    12-10 11:15:20.673: W/dalvikvm(472): Class init failed in newInstance call (Lcom/mamlambo/sample/ndk1/AndroidNDK1SampleActivity;)
    12-10 11:15:20.673: D/AndroidRuntime(472): Shutting down VM
    12-10 11:15:20.683: W/dalvikvm(472): threadid=1: thread exiting with uncaught exception (group=0×40015560)
    12-10 11:15:20.753: E/AndroidRuntime(472): FATAL EXCEPTION: main
    12-10 11:15:20.753: E/AndroidRuntime(472): java.lang.ExceptionInInitializerError
    12-10 11:15:20.753: E/AndroidRuntime(472): at java.lang.Class.newInstanceImpl(Native Method)
    12-10 11:15:20.753: E/AndroidRuntime(472): at java.lang.Class.newInstance(Class.java:1409)
    12-10 11:15:20.753: E/AndroidRuntime(472): at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
    12-10 11:15:20.753: E/AndroidRuntime(472): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1561)
    12-10 11:15:20.753: E/AndroidRuntime(472): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
    12-10 11:15:20.753: E/AndroidRuntime(472): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    12-10 11:15:20.753: E/AndroidRuntime(472): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
    12-10 11:15:20.753: E/AndroidRuntime(472): at android.os.Handler.dispatchMessage(Handler.java:99)
    12-10 11:15:20.753: E/AndroidRuntime(472): at android.os.Looper.loop(Looper.java:123)
    12-10 11:15:20.753: E/AndroidRuntime(472): at android.app.ActivityThread.main(ActivityThread.java:3683)
    12-10 11:15:20.753: E/AndroidRuntime(472): at java.lang.reflect.Method.invokeNative(Native Method)
    12-10 11:15:20.753: E/AndroidRuntime(472): at java.lang.reflect.Method.invoke(Method.java:507)
    12-10 11:15:20.753: E/AndroidRuntime(472): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    12-10 11:15:20.753: E/AndroidRuntime(472): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    12-10 11:15:20.753: E/AndroidRuntime(472): at dalvik.system.NativeStart.main(Native Method)
    12-10 11:15:20.753: E/AndroidRuntime(472): Caused by: java.lang.UnsatisfiedLinkError: Couldn’t load ndk1: findLibrary returned null
    12-10 11:15:20.753: E/AndroidRuntime(472): at java.lang.Runtime.loadLibrary(Runtime.java:429)
    12-10 11:15:20.753: E/AndroidRuntime(472): at java.lang.System.loadLibrary(System.java:554)
    12-10 11:15:20.753: E/AndroidRuntime(472): at com.mamlambo.sample.ndk1.AndroidNDK1SampleActivity.(AndroidNDK1SampleActivity.java:36)
    12-10 11:15:20.753: E/AndroidRuntime(472): … 15 more

  • JohnV

    Hi. I got *most* of the way through the tutorial, but when I run ndk-build I get this message: “/cygdrive/c/Users/John/workspace/android-ndk-r8c-windows/android-ndk-r8c/build/core/add-application.mk:128: Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml”

    Any thoughts on why? I’m stumped. Thanks in advance, John

  • Phearin

    that tutorial works out well at my side, and i’m getting to understand more about JNI from this.
    thank you…

  • Joel Odom

    This is an EXCELLENT tutorial. Got me up and running with native development very quickly. Thanks.