Get Your Eclipse-Integrated NDK On!

Sooner or later in your Android game development foray you may find the need to have some code that runs faster. It turns out that Android code written in C runs 10-100 times as fast as its Java counterpart. I can verify this, as I've already moved a few major components in my newest 3D game engine into native land. That's quite a boost but let's face it - C is a pain in the ass and while Eclipse is great for Java, it's not for C, right? Wrong. Here's how to set up a super speedy NDK development environment.

First of all, Eclipse can do way more than just Java. Java is what it's great at and what it was designed for but the architecture makes it so that it can handle any language effectively, including C. There is a component called CDT that allows for C/C++ Development in Eclipse. I'm getting ahead of myself, though. Here's what you need:

Install all 3 of those things. I like to install my NDK to c:\Android_NDK. I'll refer to that dir for the rest of this article.
Get acquainted with the NDK. You need to configure each project as an "app" in the c:\Android_NDK\apps dir. Just take a look at the examples. They work and are thorough.

How to test your NDK:
Run cygwin
cd /cygdrive/c/Android_NDK
make APP=hello-jni

It should compile without errors. If you are missing GCC or Make or any other dev packages, you will want to run your Cygwin setup again and check to make sure that all of the development packages are installed. If you have strange errors, I suggest reporting them in the NDK user's group.

Once your NDK is working, you can add an app for your project and set up the basic native framework for your project. Please refer to the examples for this part. You will need a specific build file that tells the compiler what sources to compile. JNI code is usually located in your Android project's jni folder. A file called Android.mk will need to be in there which instructs the compiler on what to compile.

After you get the basic configuration done, you will want to start writing some C. NDK uses Java's standard JNI bindings to work. All of the existing documentation on JNI should apply from this point forward. What to code is beyond the scope of this article.

Now for the good part

If you've done any NDK work, you're probably used to using a text editor or vim or some other editor to edit your C/CPP then running make APP=myapp every time to build, then clicking refresh on your project in Eclipse and then hoping that the shared object library file that gets deployed is current. What a pain in the ass! There's a much, much better way.

Now that you have CDT installed, you can edit all of your C/C++ right from Eclipse. If you right click on a C/CPP source file, just pick Open With--C/C++ Editor and it will use the CDT editor. Much nicer! It won't be able to figure out what the code is doing because it's not compiling it, but it will make editing nice and all in one spot.

Building is a snap as well. Ever used builders in Eclipse? They are configurable triggers that will execute what you configure and refresh resources for you. Make sure you know if you're on the old r3 NDK (upgrade if you are - you should be on r4) and if so, I put different instructions in this list for the different versions. Here's how I set mine up:

Right click on your project, pick properties.
Select "builders" from the left-hand list.
Click "New..." on the right side.
Select "Program" as the configuration type.
I name mine "Native Builder"
Location - c:\cygwin\bin\bash.exe
Working Directory - c:\cygwin\bin
Arguments -
(for NDK r3):
--login -c "cd /cygdrive/c/Android_NDK && make APP=myapp"
(for NDK r4):
--login -c "cd /cygdrive/c/<myapp_project_dir> && /cygdrive/c/Android_NDK/ndk-build"
Make sure you have the two hyphens before login and the quotes after the hyphen-c
Now go to the refresh tab
Check "Refresh resources upon completion"
Select "Specific resources"
Click on the "Specify resources" button and select your project's lib directory.
Check "Recursively include sub-folders"
Now go to the build options tab
Check "Allocate Console"
Check "Launch in background"
Check "Run the builder After a Clean"
Check "Run the builder During manual builds"
Check "Run the builder During auto builds"
Check "Specify working set of relevant resources"
Click on "Specify Resources"
Select your project's JNI directory and all files within.
Now click OK on the bottom.

The assumption here is that cygwin is installed to c:\cygwin, NDK is in c:\Android_NDK and your project is called "myapp". Change where appropriate.

What did you just do?! You made it so that any time you edit any files within your JNI directory and you save them, Eclipse will run the NDK Builder for you via Cygwin and show the compile output in your console. When it finishes, it will refresh your output (lib) directory which will trigger ADT to compile a new APK for you and YOU ARE GOOD TO GO!

This seriously sped me up while working on my current project. I hope you can all benefit from it!

I have same console problem ? Everything works fine, NDK/JNI/APK are all ok except I cannot see the noraml "Android" console output about AVD activities... I can see is the "**** Build of configuration Default for project XXX ****"

When you create the C/C++ project of your Android project, go to Properties -- C/C++ Build -- Environment and Add INCLUDE variable with C:\APPS\android-ndk-r4\build\platforms\android-8\arch-arm\usr\include or whatever.

Eclipse really does work pretty well but with any new IDE and build environment, there is a learning curve and this is no exception. Just check all the settings and make sure you know what is supposed to be happening and verify that it actually is :)

OK, I'm pulling out my hair here trying to get a build working with NDK r4b. I have NDK r4b, Eclipse & full CDT package installed. Trying to use your instructions, in Cygwin's bash shell I navigate to the NDK directory:

$ cd /cygdrive/c/Android/android-ndk-r4b

Then try the make:

$ make app=hello-jni

It kicks out:

make: *** No targets specified and no makefile found. Stop.

I noticed that in NDK r4b, there is no longer an "apps" directory, but they're all in a "samples" directory. If I make an "apps" directory and copy the sample code into it, I get another error:

It looks like things have been restructured so that the application.mk files are no longer in the root directories of the samples but in the 'jni' directories. Before I start monkeying around with where these things are, I thought I'd see if you have some suggestions from your experience.

Any pointers here? So far, working on this platform has been a real nightmare -- Trying to get anything done at all in Eclipse has been an uphill battle, where it sometimes builds the .spk files; other times it does not, despite no errors. Restarting Eclipse *sometimes* corrects the problem; sometimes not. While working on a project in Eclipse it'll sometimes ward about an include path that does not exist when in fact it does.

For now, Android NDK offers 'ndk-build' for us not to 'cd' to the project directory.
Arguments field can be modified as shown below. (for win32)
--login -c "ndk-build -C `cygpath -u '${build_project}' `"

I've got an approximation of this set up (in OSX) and it's working wonderfully, with one exception. I'm not getting the output from my ndk-build in the standard console. It's flashing up for half a second or so before disappearing, and I can't figure out how to either pipe it into the normal console or at least keep that output open separately. The result is that if the ndk-build fails, I'm unable to see that it has...

Robert, I sincerely thank you for this wonderful tip!
I was happy with CDT and using Eclipse to edit C/C++ files and makefiles, but I never ventured into making the process entirely automatic and efficient!

Yes, right click on the file in Package Explorer or Navigator or Java Explorer or whatever view you use to get around your project. Click Open With. If things are installed correctly, you'll have several Android options including a Layout Editor, Menu EDitor, Manifest Editor, etc. Choose Android Manifest Editor.

Question: Since I've followed these instructions, now I've lost my SDK-ish XML editor in my java projects. Its just a plain text editor and I don't have the nifty AndroidManifest.xml editor to easily handle updating my files (including the "Export APK Wizard". Any ideas?

I just fixed one issue i was facing.
changed library was not reflecting in my apk but later i realized that my project path in eclipse was different with the one i was compiling :)
its working fine now

Thanks for sharing it.
i set it up as advised but when i change anything in c file, it doesn't create new shared library.
i also changed Application.mk, removed library from lib but still getting this msg

ADC2 was a good experience and was the kind of motivation I really needed to get my butt kicked into gear. I'm glad that you enjoyed the game. For how rushed the LR3D v1.0 entry was, I was happy just to have it in the top 20.

Our new game is a world of difference in quality. I haven't posted anything yet because I'm waiting until I have something really substantial to show.

Profiling is good because it'll show you where you're really losing a lot of cycles. Working with strings is really bad. There are tons of allocations that happen even on simple concatenations.

OpenGL for sprites is really fast on any device that has hardware acceleration (a GPU). It takes a little bit of though to get your head around it because you have to set up the scene ahead of time and know to use a texture atlas and start learning about UVs on quads and such but once you get it, it's not that hard. I'm doing another 2D game after I finish my current 3D one and I'll be doing all OpenGL for it.

Using an update and draw timer is a good idea. I have an FPS counter already but obviously that doesn't give a whole lot of information about why performance has gone down. I have primarily been relying on using method tracing in Debug to figure out what causes the slowdown; it's actually been incredibly helpful. The only issue is that I can't actually run trace mode on the emulator, given that it runs about 6 times slower than the Droid. I've learned quite a lot about performance though. For instance, I had no idea how absurdly long it takes to do something like "string1" + "string2", or how much less efficient a small HashMap is compared to a small array, even if you don't use all the elements.

I just thought of another thing as well that you probably know. Does using OpenGL give a significant performance increase for drawing? For example, my app is done almost completely with sprites, so I rely quite heavily on Canvas.drawBitmap() and its overloads. I've optimized the update methods to the point where any more gains would be trivial compared to the draw time. Do you think switching to the OpenGL equivalent would net a reasonable performance increase?

I have a healthy mix of Java and C for my games. I use Java for the majority of the code and C for the really math intensive stuff, like collisions and heavy geometry operations.

The only way to find out what kind of performance you'll get on a G1 is to test on a G1-class phone. The G1, MyTouch, Eris and Hero all perform about the same because they all have the same MSM7201A chip.

What I like to do now is I run an FPS counter along with an update timer. The update timer shows me how long (in ms) my last update took. That way if the FPS drops badly, I can see if it's my update (CPU-bound) or if it's the GPU slowing down. Adding additional timers to watch AI or other things is also a good idea. More mature engines graph out these things so that you can see how several of the subsystems are performing in real-time.

Thank you for this; I will probably be setting this up for my next project. I'm barely able to chug the sort of performance I need for my current game using Java and a SurfaceView, but it's too late to justify changing now. I've had to implement a whole lot of performance optimizations, but you can only go so far. NDK should help a lot. I assume you're using C++ with OpenGL ES?

You've mentioned performance differences between G1 and the Droid before, so quick question: With my droid running my game I can get 60 fps most of the time, dropping to 40 fps when things get a bit more messy. Obviously I'll have to do some real testing on one, but do you think it would maintain 20-30 fps on the G1 given the performance on the droid? Testing on multiple phones is very difficult with how expensive they are outside of a contract...

(First sorry for my bad english)
Thank you for this great tutorial, it worked like a charm for me! Theres only one thing that i like to be available with NDK development in Eclipse: to specify where editor look for header files, so it could provide me IntelliSense like tips. I found an another tutorial about this topic here: http://cdtdoug.blogspot.com/2009/09/using-cdt-for-android-native.html this does it by converting the project into a C/C++ one. If i go into the project properties i can specify the platform headers under the C/C++ settings by pointing to the directory in the NDK's folder, so editor get knows about the code elements there. Although i don't know how to add your automatic compiling to this project, also it can't build the project anyway, Eclipse can't find make program (i guess because we didn't specify the toolchain to use for this). Do you have any suggestions what should i do to achive what i like to do?

The new project is very ambitious but is coming along. What I can say about it is that it's a first/third-person (sort-of) FPS game. It's a hybrid of things. We've spent most of our time working on the technology and so far so good, though I'm finding it difficult to work with the limitations of the G1-class GPU at the moment.

I'll be posting some screenshots and hope to have a nice demo out in a month.

A guy working directly on cdt posted something similar a couple of months ago. It's definitely a big plus whend doing ndk projects, altough build times can sometimes get on your nerves (I'm looking at you bullet physics library!).

Care to elaborate on your new project? How about doing something similar to the light racer 3d dev blog for it? I think that would make a lot of people happy, including me :)