Accessing Android Resources from C++

If you’re writing an Android game in C++ you quickly hit the problem of how to load resources (unless you are targeting Android 2.3). There are already a number of ways to do it.

I came up with a different method that I haven’t found elsewhere, so I thought I should document it. Here’s the gist of it:

Make resource IDs available in the C++ code. That is, where Java would specify a resource in the res/raw directory with R.raw.my_data, we’ll have the symbol R::raw::my_data in C++.

Write a Java method that loads and returns the bytes associated with a given resource ID.

Call this Java method from C++ to access those bytes from our C++ code.

This has the advantage that we don’t have to bloat our game code with extra copies of libraries that are already part of Android.

On to the details…

1. Resource IDs

This is an ugly preprocessor job, so if this disgusts you, you can bail out right here ;-) However once it’s done, you can forget about it. (Alternatively you could write a script to do it instead.)

The following assumes that our Java package is com.example.mygame.

We need to include the gen/com/example/mygame/R.java file in our C++ code, and make it compile. This requires a few syntax tweaks. The easy ones can be dealt with by #defining class to become namespace and defining other keywords, such as final, to become nothing.

The hard bit is dealing with the package declaration, as dots can not be used in preprocessor macro names. My approach was to define a structure that matches the package name so that com.example.mygame is a variable that exists within an unused function.

Finally, we need the values to be const, so that we don’t get link errors, so we replace int with const int.

2. Use the Android API to load resources

The following shows part of a Java wrapper around a C++ Game class. When the C++ implementation of the create() function is called, it will be passed the associated Java object. We’ll store that in our C++ code and use it later to look up and call the loadRawResource() function defined at the bottom. This function is fundamentally simple, but complicated by mandatory exception handling boilerplate.

What about drawable resources?

My original code loaded drawables using the same approach, by opening a BitmapDrawable resource: getDrawable(id) instead of openRawResource(id). Then getBitmap().copyPixelsToBuffer() gets the image data. The problem with this is that Android bitmaps use pre-multiplied alpha internally. When you use copyPixelsToBuffer(), the alpha multiplication is reversed, but if your alpha value is zero, your colour information is already gone for good. Some of my textures have zero alpha channels in order to give me additive blending (via the pre-multiplied regime described in the link above), so this resulted in blank textures. If you’re using conventional blending (or none) this may not be a problem and you can use a BitmapDrawable to load PNGs and JPEGs. Instead, I pre-process my textures into a simple uncompressed format, store them in res/raw and load them with the above loadRawResource() function.

Refinements

Recently I developed a PC build of my game, for debugging and video capture, which uses a script to generate a mapping from resource ID to filename. I am starting to think that a script may be the way to go for all platforms, replacing step (1) above. In addition to generating a nice clean header file for resource IDs, it could generate the resource lists that I currently use to pre-load all my textures at start-up, which are currently hand coded. Parts (2) and (3) would continue to do the actual loading on Android.