Building GDAL using Android NDK on Linux

Warning! this is still a work in progress!

This procedure was developed on a Linux system using Android NDK r5b and is based on information from this thread:  http://groups.google.com/group/android-ndk/browse_thread/thread/9988752f332eff45

Cross compiling GDAL

First, a standalone toolchain is created to make the configure script easier to use. (See android-ndk-r5b/docs/STANDALONE-TOOLCHAIN.html for more details)

~$ android-ndk-r5b/build/tools/make-standalone-toolchain.sh --platform=android-8 --install-dir=android-8-toolchain

Next, the toolchain's bin directory is added to the PATH.

~$ export PATH=$PATH:~/android-8-toolchain/bin/

From the GDAL source directory, configure for cross compiling and make. (This assumes config.guess and config.sub where updated. Latest versions can be found here:  http://git.savannah.gnu.org/cgit/config.git/tree/)

Older GDAL versions (before r21653 - includes 1.8.0)

before compiling, patch the source with the patch given at http://trac.osgeo.org/gdal/ticket/3952

Newest GDAL versions after r22958 (including 1.9)

as below, but --without-grib is not needed anymore

All GDAL versions

gdal$ CFLAGS="-mthumb" CXXFLAGS="-mthumb" LIBS="-lsupc++ -lstdc++" \
      ./configure --host=arm-linux-androideabi --without-grib --prefix=$PROJECT/external/gdal
gdal$ make
gdal$ make install

The $PROJECT variable contains the path to where you want your Android NDK modules to live.

In $PROJECT/external/gdal, an Android.mk file is created with the following contents:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := gdal
LOCAL_SRC_FILES := lib/libgdal.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_LDLIBS := -lz
include $(PREBUILT_STATIC_LIBRARY)

Using in a JNI library

Here's a HelloGdal app to test the use of the library as part of a JNI component of an Android project.

In the project's jni directory, hello-jdal.cpp was create with the following contents:

#include <jni.h>
#include <ogr_api.h>
#include <sstream>

extern "C" {
    JNIEXPORT jstring
    JNICALL Java_org_gdal_HelloGdal_stringFromGDAL(JNIEnv*env, jobject thiz);
}

JNIEXPORT jstring
JNICALL Java_org_gdal_HelloGdal_stringFromGDAL(JNIEnv* env, jobject thiz)
{
    OGRRegisterAll();
    std::ostringstream drivers;
    drivers << "OGR Drivers:\n";
    for (int i = 0; i < OGRGetDriverCount(); ++i)
        drivers << "\t" << OGR_Dr_GetName(OGRGetDriver(i)) << "\n";

    return env->NewStringUTF(drivers.str().c_str());
}

(Yes, I know, it's called HelloGdal, yet it lists the OGR drivers. I'll leave it as an exercise to have the GDAL drivers listed)

Here's the corresponding Android.mk file:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-gdal
LOCAL_SRC_FILES := hello-gdal.cpp
LOCAL_STATIC_LIBRARIES := gdal
include $(BUILD_SHARED_LIBRARY)
$(call import-module,gdal)

The path to the external GDAL module is set and the library is built using the NDK's build process.

jni$ export NDK_MODULE_PATH=$PROJECT/external
jni$ $NDK_ROOT/ndk-build

Finally, the Java portion that uses the JNI library.

package org.gdal;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;


public class HelloGdal extends Activity {
	
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView  tv = new TextView(this);
        tv.setText( stringFromGDAL() );
        setContentView(tv);
    }
	
	public native String stringFromGDAL();
	
	static {
        System.loadLibrary("hello-gdal");
    }
    	
}

SWIG bindings

You can build and adapt the Java Swig bindings to expose whole GDAL API to the Java portion of an Android application. It needs just one change in typemaps_java.i, see full instructions covering all Android platforms:  https://github.com/nutiteq/gdal/wiki