This is a tiny demonstration of using OpenGL ES in C++ on an Android 2.2 phone. It’s theme is ‘Faceinspaders !’ which is a small multiplayer game that I’ve been building in my spare time. The demonstration is part of my experiment in trying to port this code, which already builds on Windows as well as Linux to the Android platform.
(scroll to the end of the page to download the APK file and source code)
The code runs in Windows as well and the download package also contains a Visual Studio solution file in the ‘jni/faceinspaders’ directory.
The ‘Faceinspaders !’ project is still unreleased and is not nearly finished but I thought that the initial results of trying to port some C++ code to Android 2.2 was worth writing an article about. Mainly because it was not as trivial as I though it would be.
Some of the challenges being:
- On Android you will pretty much have to bootstrap you code from Java, or Dalvik as its VM is called.
- Your code will be packed into an APK file, which is basically a .zip file in disguise. So you will have to do a bit more to get to your resources.
- OpenGL ES is not exactly OpenGL. I’ve spend a surprising amount of time looking at white textures or blank screens while everything looked fine in Windows.
Here’s a video of the demonstration running:
Bootstrapping the code
Google really wants you to program in Java. The main reason seems to be stability. Since your code would run in a Dalvik sandbox there’s little risk of your app crashing an entire phone. This means that no matter what you ultimately want to do, you’re going to have to install their Java based SDK first.
So to get started download their SDK which also contains a virtual Android device which is an Android simulator. Also download the Eclipse Java IDE to be able to use the Android Development Tools plugin for it. The ADT plugin allows you to create Android projects which will automatically generate APK package files of your code, including your native code.
Now you’re all set up to start programming Android devices in Java. But since this is about C++ code, you’re going to need another download. The Android NDK. Since Android is actually a Linux based platform even the Window download requires you to have Cygwin installed. Just a basic install of Cygwin will do, but don’t forget to check the ‘GNU make’ package.
At this point all of the online documentation should be sufficient in describing how to create an Android.mk file and an Application.mk file to get you application to build.
It’s time to think about how the C++ code is going to be called from inside Java. Here are a couple of things I found I had to take into consideration:
- The Android ‘Activity’ interface in combination with the ‘GLSurfaceView’ interface will have you calling JNI methods from different Threads.
- There does not seem to be a nice C++ API to access the touch senses on your device.
If you have build your application to run from one context only, like I did, you will be scratching your head for a while if you don’t immediately realize that the GLSurfaceView draw() and resize() methods will be called from a dedicated OpenGL thread which is a different thread from, say, the thread that will call onCreate() or onStop() in your Activity.
You can solve this by synchronizing from the inside the Java code, but since I just wanted to go back to C++ as quickly as possible, I created a synchronized object in C++. Since Android does include the POSIX pthread library.
And because of the lack of native touch library you will be stuck with getting the touch events from the Java framework and passing them on to you C++ code.
Getting resouces from the APK file
If you are working in Java this could not be any easier. Just put it in the ‘res’ directory and refer to it from the R.java file. But we’re not working from Java so we have a couple of options:
- Use libzip and extract everything you need yourself.
- Use Android 2.3 or higher which has a lot of improvents in the native interface.
- Get a Java JNI thing going, like passing some sort of Stream object through to your C++ code.
- Your own creative solution here…
I went for the first option because my only Android device is an HTC Desire which still runs Android 2.2.
The libzip API is actually pretty straightforward and easy to use. The biggest hurdle was finding a way to build it as a static library using .mk files and linking to it. But since you are reading this, just download my source code and copy my libzip configuration
Running on OpenGL ES
OpenGL ES contains a subset of the OpenGL functionality and adds fixed point arithmetics to the library.
If you are already familiar with OpenGL then it should be fairly easy to pick up. If you’re not already familiar with OpenGL then it’s definitly not easy to pick up. This is mainly due to OpenGL ES loosing a number of things that kept OpenGL at least somewhat accessible to newcomers.
These are some of the things to get used to:
- There’s no more glBegin and glEnd. If you’re going to do anything your going to be using vertex arrays.
- You can’t use Quads any more.
- Your textures hight and width really need to be powers of two.
So if you’re just trying to get that first rotating and textured cube you are going to have to put in a little more effort. But otherwise it does feel familiar enough and it performs pretty good.
Also, since you are bootrapping from Java, keep in mind that all OpenGL ES code needs to run from the GLSurfaceView draw() or resize() thread.
Stars APK File Extract this and put the APK file on your Android device. Install using an ‘App installer’ application.
Stars sources Run ndk-build on the JNI directory first and build the Eclipse project second.