Android Port – First Light

I bought myself and Android (2.1) HTC Legend phone. Obviously, the first thing I wanted to do was to get haxe/NME running on it. Now the Android platform is very well setup for Java development but, unfortunately, the haxe Java target is not fully developed at the moment. Luckily, there is also a “native” development kit (NDK) that allows you to run c++ code on the device using a Java bootstrap to load the code and JNI.

The NDK is based in the GCC toolchain, and therefore is already pretty well supported by the hxcpp haxe backend. The problem is that the standard NDK is somewhat crippled – it does not support exceptions or the STL. It is possible to rework the hxcpp backend to work without the STL, but removing exceptions may take a bit more work. I managed to work around this by using a slightly modified NDK, created by a very helpful member of the comminity over at crystax.net. In theory this should have been all that was required, however the NDK also lacks proper wchar_t support. When I finally worked this out, it was reasonably easy to substitute a simple translation layer to fix these wide-char problems.
So far, I have only implemented the rendering API, with no interactive options. The OpenGL ES rendering code is exactly the same as for the iPhone, except that the initial context and display surface are setup in the Java code, rather than the Objective C code.

Developing with haxe for the Android target requires several modules to work together. First, you compile your haxe code as normal to a shared object – which is actually a JNI module. This exposes a single “main” function that can be called from Java. Your actual Android application starts with Java code, and you can setup the properties etc. from eclipse. Ultimately this will be boilerplate code and you will only need to change the bits you need to. This Java code then calls the haxe main function. In the graphical/NME environment the main thing this does is dynamically load the nme native library and setup a callback for when the graphics are finally initialized. You then return to Java code and setup a OpenGL ES context. When this is done, a JNI call is made into the nme dynamic library, which in turn calls back into your haxe application to complete setup. The “MainLoop” is then processed in Java, and events such as “Redraw” (and later “OnMouse” etc) are passed into the nme library, and then into the haxe application as registered “addEventListeners”.

So in this somewhat convoluted way, Java maintains full control of the app, and therefore correct interaction with the OS, while almost all the real work is done in the haxe code. In the example shown here, no changes were necessary to the haxe code, and the internal garbage collection also worked without modification, so it is a pretty solid cross-platform solution.

Now the bad news. The performance is way down compared to my 2nd generation iPod touch. This example is 10fps on the Android device, and about 24 on the iPod. Which is strange, because the core should actually be running a bit faster. The slowdown seems to be on both the OpenGL side, and the physics calculation side. It should also be noted that this is a first pass, so there is quite a bit of room for improvement. My guess is that the gcc compiler is generating significant runtime overhead per function because of the exception code. This is what I noted while compiling for the iPhone (it was doing a pthread lock per function!) \- but in that case the penalty was only incurred in functions that actually “threw”, so I simply moved the throwing code into a separate function. Which brings me to my second problem …

No easy profiling or debugging support for native code. This is a real pain for debugging (back to “log” debugging) and the lack of profiling makes it very hard to work out what needs optimizing for the target. I may be able to use a simple “setjump” style system for exceptions because the use of garbage collection means that there are no real destructors required for cleanup. But I would need to be sure this would help – premature optimization and all that.

I would also count the fact that you really need to use eclipse as an IDE as a big negative, but I think that this is just my personal dislike of the program. I think there may ultimately be ways around this with command-line compilers etc.

Native compiling tools for the Android target are still in active development and moving forwards, so I’m assuming that most of these problems will be overcome eventually. And of course, the big advantage of the Android OS is the openness \- so I can provide you with the actual application to run on your device \- give it a go, and let me know if it runs for you.

10 Replies to “Android Port – First Light”

    1. Simon,
      Interesting to see better results – I think I should be able to do even better though. And re:eclipse, I sad it was personal – I guess I’m a “vi” guy at heart.

  1. huge
    🙂
    works great on nexus but small even on wide screen so can’t read frame rate. also no left right key I can use. would love to start experimenting, could I compile using haxe and android textmate bundles, is there a tut coming or a time when your on irc and I can bug you to help me set up? ;j (posted from my nexus)

  2. wchar_t is just a mess… it doesn’t give you constant-time lookups like UCS-4/UTF-32 would, and for most of the world’s text, UTF-8 is more compact that UTF-16. If your system APIs require wchar_t’s odd mix of 2-byte and 4-byte characters, then it’s probably best to wrap the system APIs in translation code and use UTF-8 internally. UTF-16 is a mistake, and the main reason the mistake persists is that Windows Unicode support, Java, and JavaScript were all started when it appeared that UCS-2 would be sufficient for all the world’s languages.

Leave a Reply to Andy Li Cancel reply

Your email address will not be published. Required fields are marked *