Application note - using FLTK on Android

2016/02/23

1. Introduction

This project is based on the Android NDK (native development kit) and the JNI interface.
The JNI (Java native interface) was developed to allow Java applications to access
libraries written in C/C++. JNI has been part of Java for a long time.

JNI allows to compile C/C++ code to libraries that can be called from an Android JAVA
program. So you make a tiny JAVA program and a bigger C/C++ library with your code.

This project is based on the Allegro graphics library which can be used with Android.
To compile this library you install an Android toolchain which can also be used to
cross-compile FLTK.
Between FLTK and Allegro there is the Microwindows/PX11 library which is used instead
of the standard X11 library. PX11 is the NX11 and nano-X libraries linked together.
This Microwindows/PX11 library is also cross-compiled for Android.
This library features screen, mouse and keyboard drivers for Allegro so the Allegro
graphics library can be used as a backend for Microwindows/PX11.

The Allegro and PX11 libraries together allow to compile FLTK programs for Android.
These get compiled to shared libraries which link FLTK, PX11 and Allegro and are called
from a tiny JAVA program for Android.

So you have to compile an FLTK program to a shared library and not to an elf executable.
Then you need a "stub" Java program that calls your FLTK program which is compiled to a
shared library. Once the FLTK shared library "program" is called it works (within limits)
like a normal FLTK program. In addition you link libfltk.a etc. to this project.

2. Installing the Android cross-compiling environment.

Since you will not compile on your Android device, you need a cross compile environment
to develop applications for the Android device.

For this you have to download ant, the JAVA Development Kit for Java from Oracle directly,
the Android SDK and the Android NDK. Then you have to setup the Android SDK which means
you have to download various packages for it.

Then you need to specify required environment variables and generate a standalone toolchain.
After that you can connect your Android device to your PC.

All this is described in detail in this Wiki page that I wrote:

Running_Allegro_applications_on_Android

You can skip for now the section "Compile Allegro for Android " since these libraries are
already included as binaries on Github. This to save you the time to compile these.

3. Compile and run the test and demo programs for the Android device

A Microwindows package containing a src/android directory with already compiled libraries
for your convenience is kept in a separate repository. If you have not already done so, download
this from here:
https://github.com/georgp24/microwindows-android-bin

After you have completed the steps outlined above and the environment variables are set,
you get into the "microwindows/src/android/" directory. This contains the ex_fltk.project
directory and the ex_nanox.project directory.

The ex_fltk.project directory is setup to compile FLTK C++ programs while the ex_nanox.project
directory is set up to compile the nano-x demo programs in C. The difference between these two
directories is the line to the source code file in the jni/Android.mk makefile. This makefile
also determines that the libfltk.a and libPX11.a libraries are linked with the application.

In the ex_nanox.project directory the APK file ex_nanox-debug.apk will be compiled while
in the ex_fltk.project directory the APK file ex_fltk-debug.apk will be generated.

In both directories there are two files where you have to edit the path to your home directory:
"local.properties" and "localgen.properties". Please do that now.

Then go into the ex_fltk.project directory. In there you will find the csrc directory
and in there the file ex_fltk.cpp. This is the source file that will be compiled. If you e.g.
want to compile the editor.cxx program you have to copy it to the name of ex_fltk.cpp.
There is a script in this directory called "copy-from-test.sh" which will list the files
in the fltk test directory (check the path in the script) and copy the selected file to
ex_fltk.cpp in the csrc directory. If you would not copy the file to this name, you would
have to make separate project directories for each source file.

Then you can get back into the ex_fltk.project directory and execute the "run.sh" script.
This will generate the ex_fltk-debug.apk file and install and run it on the Android device.
See the Wiki page why you need to compile these APKs in debug mode.

The same procedure applies to the ex_nanox.project/csrc directory. In there the file
ex_nanox.c will be compiled and you can use the "copy-from-nanox.sh" script there for your
convenience.

You do not need to include Android or Allegro headers in your programs. Only if you want
to use logcat for debugging, you have to add "#include <android/log.h>".

If you add libraries you have to check that these are included in your java program
"src/org/liballeg/example/ExampleActivity.java". E.g.:

 System.loadLibrary("allegro_font-debug");
to load the allegro_font-debug.so library.

Read the Wiki page for further information how to make Android applications.

The following sections cover instructions how to compile the libraries that are
already included in binary form.


4. Compile and install Allegro for Android

If you want to compile the Allegro libraries from scratch, please follow the section
"Compile Allegro for Android" on the Wiki page:
Running_Allegro_applications_on_Android

When done copy the resulting libraries from buildandroid/lib into
microwindows/src/android/buildandroid/lib.

5. Cross compile the freetype library

To run FLTK you need the freetype library. There is a section in the Wiki page
called "Build dependency libraries - libfreetype" which describes how to do that.

When done copy the resulting library into microwindows/src/android/buildandroid/lib.
I renamed the library to libfreetype-android.a to avoid confusion with the freetype
library in /usr/lib. Thus it is also in the Android.mk makefile under this name plus
in the src/Configs/config.allegro-android file.

6. Cross-compile PX11

Microwindows is a small X11 compatible library for embedded devices. It started with
nano-X which later got a wrapper to make it more X11 compatible called NX11. Currently
the nano-X and NX11 libraries are compiled to one library called PX11. We will use this
here since it is more convenient than using two separate libraries.

Download the current Microwindows library from Github if you have not already done so:
https://github.com/ghaerr/microwindows
Click on the "Download ZIP" button to download it as a ZIP file.

Unzip that file into your home directory naming it microwindows.

Microwindows does not have a configure script. It uses a Makefile system which
gets configured with the "config" file.In the src/configs directory you will find
an config.android file which you have to copy into the src directory and name it just
"config". Replacing the default "config" file in the src directory.

Then set the environment variables so Microwindows will be compiled with the
Android toolchain. You probably already have done that, it is described in the
Wiki page.

Now enter "make" in the src directory and Microwindows should compile for Android.

In the src/lib directory you will find a new libPX11.a library which you have to copy
to the "microwindows/src/android/buildandroid/lib" directory.

Then copy the "X11" directory from the src/nxlib/ directory to the
"microwindows/src/android/buildandroid/include" directory.

Plus add the cursorfont.h and Xlocale.h headers from your /usr/include/X11
directory into this directory.

7. Cross-compile FLTK

First check that you have set the environment variables required for cross compiling
for Android.

Since you have to pass a lot of options to configure I use the following script:

export CXXFLAGS=-fno-rtti

./configure --disable-gl \
  --disable-xinerama \
  --disable-xft  \
  --disable-xdbe \
  --disable-xfixes \
  --disable-localjpeg \
  --disable-localpng \
  --disable-localzlib \
  --disable-threads \
  --host=arm-linux-androideabi \
  --target=arm-linux-androideabi \
  --prefix=/home/georg/android-toolchain/sysroot/usr \
  --exec_prefix=/home/georg/android-toolchain/sysroot/usr \
  --x-includes=/home/georg/microwindows-android/src/nxlib/X11 \
  --x-libraries=/home/georg/microwindows-android/src/lib 
You will have to change "/home/georg" to your home directory path.

After running this script you have to manually replace -lX11 with -lPX11 in the
makeinclude file or use the replace-lX11.sh script for that:
LDLIBS		= -ldl -lm  -lPX11 
GLDLIBS		=  -ldl -lm  -lPX11 
If you are using FLTK 1.3.3 you will now have to patch the file:
"src/Fl_Native_File_Chooser_FLTK.cxx"

In there commment out the line 28:
//#include "Fl_Native_File_Chooser_GTK.cxx"
and the line 56:
//Fl_GTK_File_Chooser::probe_for_GTK_libs();
and change the lines 76-77 to:
  //if (Fl_GTK_File_Chooser::did_find_GTK_libs) _gtk_file_chooser = new Fl_GTK_File_Chooser(val);
  //else 
  _x11_file_chooser = new Fl_FLTK_File_Chooser(val);
Then you can enter "make" to compile FLTK for Android. Make will stop when compiling
fluid but that does not matter since we do not want to use fluid on Android. But the
libraries libfltk.a, libfltk-forms.a and libfltk-images.a, are compiled in the "libs" directory.
Copy libfltk.a to the "microwindows/src/android/buildandroid/lib" directory.

Then copy the "FL" directory from the fltk directory to the
"microwindows/src/android/buildandroid/include" directory.

The default stdc++ library for Android has a very limited functionality. Therefore
you find the -fno-rtti and -fno-exceptions flags in the makeinclude file.

23rd of February 2016, Georg Potthast