From c3fb2e06f19deb50a40045406921aad2e9689dd7 Mon Sep 17 00:00:00 2001
From: Sebastian Krzyszkowiak <dos@dosowisko.net>
Date: Mon, 7 Nov 2016 01:45:12 +0100
Subject: [PATCH] more robust Android support

---
 android/AndroidManifest.xml.in                | 20 ++++
 android/ant.properties                        | 17 ++++
 android/build.xml.in                          | 95 +++++++++++++++++++
 android/custom_rules.xml                      | 19 ++++
 android/jni/Application.mk                    |  3 +
 android/jni/localgen.mk.in                    | 12 +++
 android/localgen.properties.in                |  1 +
 android/proguard-project.txt                  | 20 ++++
 android/project.properties.in                 | 11 +++
 android/res/layout/main.xml                   | 13 +++
 android/res/values/strings.xml.in             |  4 +
 .../SuperDerpyActivity.java.debug.in          | 28 ++++++
 .../libsuperderpy/SuperDerpyActivity.java.in  | 28 ++++++
 cmake/FindAllegro5.cmake                      |  1 +
 cmake/FindAllegro5ACodec.cmake                |  1 +
 cmake/FindAllegro5Audio.cmake                 |  1 +
 cmake/FindAllegro5Color.cmake                 |  1 +
 cmake/FindAllegro5Font.cmake                  |  1 +
 cmake/FindAllegro5Image.cmake                 |  1 +
 cmake/FindAllegro5Primitives.cmake            |  1 +
 cmake/FindAllegro5TTF.cmake                   |  1 +
 cmake/android.toolchain                       | 24 ++++-
 cmake/libsuperderpy.cmake                     | 86 +++++++++++++++++
 src/defines.h.in                              | 10 ++
 src/libsuperderpy.c                           |  2 +
 25 files changed, 400 insertions(+), 1 deletion(-)
 create mode 100644 android/AndroidManifest.xml.in
 create mode 100644 android/ant.properties
 create mode 100644 android/build.xml.in
 create mode 100644 android/custom_rules.xml
 create mode 100644 android/jni/Application.mk
 create mode 100644 android/jni/localgen.mk.in
 create mode 100644 android/localgen.properties.in
 create mode 100644 android/proguard-project.txt
 create mode 100644 android/project.properties.in
 create mode 100644 android/res/layout/main.xml
 create mode 100644 android/res/values/strings.xml.in
 create mode 100644 android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.debug.in
 create mode 100644 android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.in
 create mode 100644 src/defines.h.in

diff --git a/android/AndroidManifest.xml.in b/android/AndroidManifest.xml.in
new file mode 100644
index 0000000..d793a20
--- /dev/null
+++ b/android/AndroidManifest.xml.in
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="net.dosowisko.${LIBSUPERDERPY_GAMENAME}"
+      android:versionCode="1"
+      android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="15"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
+    <application android:label="@string/app_name" android:debuggable="true">
+        <activity android:name="net.dosowisko.${LIBSUPERDERPY_GAMENAME}.SuperDerpyActivity"
+                  android:label="@string/app_name"
+                  android:launchMode="singleTask"
+                  android:screenOrientation="unspecified"
+                  android:configChanges="screenLayout|uiMode|orientation">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest> 
diff --git a/android/ant.properties b/android/ant.properties
new file mode 100644
index 0000000..ee52d86
--- /dev/null
+++ b/android/ant.properties
@@ -0,0 +1,17 @@
+# This file is used to override default values used by the Ant build system.
+#
+# This file must be checked in Version Control Systems, as it is
+# integral to the build system of your project.
+
+# This file is only used by the Ant script.
+
+# You can use this to override default values such as
+#  'source.dir' for the location of your java source folder and
+#  'out.dir' for the location of your output folder.
+
+# You can also use it define how the release builds are signed by declaring
+# the following properties:
+#  'key.store' for the location of your keystore and
+#  'key.alias' for the name of the key to use.
+# The password will be asked during the build when you use the 'release' target.
+
diff --git a/android/build.xml.in b/android/build.xml.in
new file mode 100644
index 0000000..5c23ed0
--- /dev/null
+++ b/android/build.xml.in
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="@LIBSUPERDERPY_GAMENAME@" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- This file is generated by CMake. -->
+    <property file="localgen.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var.
+         This must be done before we load project.properties since
+         the proguard config can use sdk.dir -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/android/custom_rules.xml b/android/custom_rules.xml
new file mode 100644
index 0000000..6c40960
--- /dev/null
+++ b/android/custom_rules.xml
@@ -0,0 +1,19 @@
+<project>
+    <!-- Overriding jar.libs.dir is broken from some SDK version onwards
+         and seems like it won't be fixed:
+         https://code.google.com/p/android/issues/detail?id=33194
+
+         This workaround is from:
+         http://stackoverflow.com/questions/11637852
+    -->
+    <property file="localgen.properties" />
+    <target name="-pre-compile">
+        <path id="project.all.jars.path">
+            <path path="${toString:project.all.jars.path}"/>
+            <fileset dir="${jar.libs.dir}">
+                <include name="*.jar"/>
+            </fileset>
+        </path>
+    </target>
+</project>
+<!-- vim: set ft=ant et: -->
diff --git a/android/jni/Application.mk b/android/jni/Application.mk
new file mode 100644
index 0000000..c17f980
--- /dev/null
+++ b/android/jni/Application.mk
@@ -0,0 +1,3 @@
+include $(call my-dir)/localgen.mk
+APP_PLATFORM := android-15
+APP_ABI := $(TARGET_ARCH_ABI)
diff --git a/android/jni/localgen.mk.in b/android/jni/localgen.mk.in
new file mode 100644
index 0000000..7ebc942
--- /dev/null
+++ b/android/jni/localgen.mk.in
@@ -0,0 +1,12 @@
+# Absolute paths to Allegro source and build directories.
+CMAKE_SOURCE_DIR := ${CMAKE_SOURCE_DIR}
+CMAKE_BINARY_DIR := ${CMAKE_BINARY_DIR}
+
+# Relative path to prebuilt Allegro libraries from LOCAL_PATH.
+RELATIVE_LIB_DIR := ${RELATIVE_LIB_DIR}
+
+# Library type suffix on Allegro libraries, e.g. "-debug".
+# XXX changing this requires manual editing of the System.loadLibrary calls
+LIB_TYPE_SUFFIX := ${LIB_TYPE_SUFFIX}
+
+TARGET_ARCH_ABI := ${ARM_TARGETS}
diff --git a/android/localgen.properties.in b/android/localgen.properties.in
new file mode 100644
index 0000000..457f12a
--- /dev/null
+++ b/android/localgen.properties.in
@@ -0,0 +1 @@
+jar.libs.dir=${LIBRARY_OUTPUT_PATH}
diff --git a/android/proguard-project.txt b/android/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/android/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/android/project.properties.in b/android/project.properties.in
new file mode 100644
index 0000000..26012c0
--- /dev/null
+++ b/android/project.properties.in
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=@ANDROID_TARGET@
diff --git a/android/res/layout/main.xml b/android/res/layout/main.xml
new file mode 100644
index 0000000..1819004
--- /dev/null
+++ b/android/res/layout/main.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView  
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:text="libsuperderpy"
+    />
+</LinearLayout>
+
diff --git a/android/res/values/strings.xml.in b/android/res/values/strings.xml.in
new file mode 100644
index 0000000..dc697ce
--- /dev/null
+++ b/android/res/values/strings.xml.in
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">${LIBSUPERDERPY_GAMENAME_PRETTY}</string>
+</resources>
diff --git a/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.debug.in b/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.debug.in
new file mode 100644
index 0000000..892ca66
--- /dev/null
+++ b/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.debug.in
@@ -0,0 +1,28 @@
+package net.dosowisko.${LIBSUPERDERPY_GAMENAME};
+
+import org.liballeg.android.AllegroActivity;
+
+public class SuperDerpyActivity extends AllegroActivity {
+
+   /* Load Allegro and other shared libraries in the lib directory of the apk
+    * bundle.  You must load libraries which are required by later libraries
+    * first.
+    */
+   static {
+      System.loadLibrary("allegro-debug");
+      System.loadLibrary("allegro_primitives-debug");
+      System.loadLibrary("allegro_image-debug");
+      System.loadLibrary("allegro_font-debug");
+      System.loadLibrary("allegro_ttf-debug");
+      System.loadLibrary("allegro_audio-debug");
+      System.loadLibrary("allegro_acodec-debug");
+   }
+
+   /* By default, AllegroActivity.onCreate will cause Allegro to load the
+    * shared object `libapp.so'.  You can specify another library name by
+    * overriding the constructor.
+    */
+   public SuperDerpyActivity() {
+      super("libgame.so");
+   }
+}
diff --git a/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.in b/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.in
new file mode 100644
index 0000000..60a251e
--- /dev/null
+++ b/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.in
@@ -0,0 +1,28 @@
+package net.dosowisko.${LIBSUPERDERPY_GAMENAME};
+
+import org.liballeg.android.AllegroActivity;
+
+public class SuperDerpyActivity extends AllegroActivity {
+
+   /* Load Allegro and other shared libraries in the lib directory of the apk
+    * bundle.  You must load libraries which are required by later libraries
+    * first.
+    */
+   static {
+      System.loadLibrary("allegro");
+      System.loadLibrary("allegro_primitives");
+      System.loadLibrary("allegro_image");
+      System.loadLibrary("allegro_font");
+      System.loadLibrary("allegro_ttf");
+      System.loadLibrary("allegro_audio");
+      System.loadLibrary("allegro_acodec");
+   }
+
+   /* By default, AllegroActivity.onCreate will cause Allegro to load the
+    * shared object `libapp.so'.  You can specify another library name by
+    * overriding the constructor.
+    */
+   public SuperDerpyActivity() {
+      super("libgame.so");
+   }
+}
diff --git a/cmake/FindAllegro5.cmake b/cmake/FindAllegro5.cmake
index 85be126..4304792 100644
--- a/cmake/FindAllegro5.cmake
+++ b/cmake/FindAllegro5.cmake
@@ -17,6 +17,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALLEGRO5 DEFAULT_MSG ALLEGRO5_LIBRARY ALLEGRO5
 
 IF(ALLEGRO5_FOUND)
   SET(ALLEGRO5_LIBRARIES ${ALLEGRO5_LIBRARY})
+  SET(ALLEGRO5_LIBS ${ALLEGRO5_LIBS} ${ALLEGRO5_LIBRARIES})
 ENDIF(ALLEGRO5_FOUND)
 
 MARK_AS_ADVANCED(ALLEGRO5_LIBRARY ALLEGRO5_INCLUDE_DIR )
diff --git a/cmake/FindAllegro5ACodec.cmake b/cmake/FindAllegro5ACodec.cmake
index 8a69d9b..c77c094 100644
--- a/cmake/FindAllegro5ACodec.cmake
+++ b/cmake/FindAllegro5ACodec.cmake
@@ -17,6 +17,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALLEGRO5_ACODEC DEFAULT_MSG ALLEGRO5_ACODEC_LI
 
 IF(ALLEGRO5_ACODEC_FOUND)
   SET(ALLEGRO5_ACODEC_LIBRARIES ${ALLEGRO5_ACODEC_LIBRARY})
+  SET(ALLEGRO5_LIBS ${ALLEGRO5_LIBS} ${ALLEGRO5_ACODEC_LIBRARIES})
 ENDIF(ALLEGRO5_ACODEC_FOUND)
 
 MARK_AS_ADVANCED(ALLEGRO5_ACODEC_LIBRARY ALLEGRO5_ACODEC_INCLUDE_DIR )
diff --git a/cmake/FindAllegro5Audio.cmake b/cmake/FindAllegro5Audio.cmake
index 316589d..7f99ad6 100644
--- a/cmake/FindAllegro5Audio.cmake
+++ b/cmake/FindAllegro5Audio.cmake
@@ -17,6 +17,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALLEGRO5_AUDIO DEFAULT_MSG ALLEGRO5_AUDIO_LIBR
 
 IF(ALLEGRO5_AUDIO_FOUND)
   SET(ALLEGRO5_AUDIO_LIBRARIES ${ALLEGRO5_AUDIO_LIBRARY})
+  SET(ALLEGRO5_LIBS ${ALLEGRO5_LIBS} ${ALLEGRO5_AUDIO_LIBRARIES})
 ENDIF(ALLEGRO5_AUDIO_FOUND)
 
 MARK_AS_ADVANCED(ALLEGRO5_AUDIO_LIBRARY ALLEGRO5_AUDIO_INCLUDE_DIR )
diff --git a/cmake/FindAllegro5Color.cmake b/cmake/FindAllegro5Color.cmake
index 2321190..be0ef00 100644
--- a/cmake/FindAllegro5Color.cmake
+++ b/cmake/FindAllegro5Color.cmake
@@ -17,6 +17,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALLEGRO5_COLOR DEFAULT_MSG ALLEGRO5_COLOR_LIBR
 
 IF(ALLEGRO5_COLOR_FOUND)
   SET(ALLEGRO5_COLOR_LIBRARIES ${ALLEGRO5_COLOR_LIBRARY})
+  SET(ALLEGRO5_LIBS ${ALLEGRO5_LIBS} ${ALLEGRO5_COLOR_LIBRARIES})
 ENDIF(ALLEGRO5_COLOR_FOUND)
 
 MARK_AS_ADVANCED(ALLEGRO5_COLOR_LIBRARY ALLEGRO5_COLOR_INCLUDE_DIR )
diff --git a/cmake/FindAllegro5Font.cmake b/cmake/FindAllegro5Font.cmake
index 860c155..ea1c3a1 100644
--- a/cmake/FindAllegro5Font.cmake
+++ b/cmake/FindAllegro5Font.cmake
@@ -17,6 +17,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALLEGRO5_FONT DEFAULT_MSG ALLEGRO5_FONT_LIBRAR
 
 IF(ALLEGRO5_FONT_FOUND)
   SET(ALLEGRO5_FONT_LIBRARIES ${ALLEGRO5_FONT_LIBRARY})
+  SET(ALLEGRO5_LIBS ${ALLEGRO5_LIBS} ${ALLEGRO5_FONT_LIBRARIES})
 ENDIF(ALLEGRO5_FONT_FOUND)
 
 MARK_AS_ADVANCED(ALLEGRO5_FONT_LIBRARY ALLEGRO5_FONT_INCLUDE_DIR )
diff --git a/cmake/FindAllegro5Image.cmake b/cmake/FindAllegro5Image.cmake
index 20d89fc..2a96268 100644
--- a/cmake/FindAllegro5Image.cmake
+++ b/cmake/FindAllegro5Image.cmake
@@ -17,6 +17,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALLEGRO5_IMAGE DEFAULT_MSG ALLEGRO5_IMAGE_LIBR
 
 IF(ALLEGRO5_IMAGE_FOUND)
   SET(ALLEGRO5_IMAGE_LIBRARIES ${ALLEGRO5_IMAGE_LIBRARY})
+  SET(ALLEGRO5_LIBS ${ALLEGRO5_LIBS} ${ALLEGRO5_IMAGE_LIBRARIES})
 ENDIF(ALLEGRO5_IMAGE_FOUND)
 
 MARK_AS_ADVANCED(ALLEGRO5_IMAGE_LIBRARY ALLEGRO5_IMAGE_INCLUDE_DIR )
diff --git a/cmake/FindAllegro5Primitives.cmake b/cmake/FindAllegro5Primitives.cmake
index a893633..9bed349 100644
--- a/cmake/FindAllegro5Primitives.cmake
+++ b/cmake/FindAllegro5Primitives.cmake
@@ -17,6 +17,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALLEGRO5_PRIMITIVES DEFAULT_MSG ALLEGRO5_PRIMI
 
 IF(ALLEGRO5_PRIMITIVES_FOUND)
   SET(ALLEGRO5_PRIMITIVES_LIBRARIES ${ALLEGRO5_PRIMITIVES_LIBRARY})
+  SET(ALLEGRO5_LIBS ${ALLEGRO5_LIBS} ${ALLEGRO5_PRIMITIVES_LIBRARIES})
 ENDIF(ALLEGRO5_PRIMITIVES_FOUND)
 
 MARK_AS_ADVANCED(ALLEGRO5_PRIMITIVES_LIBRARY ALLEGRO5_PRIMITIVES_INCLUDE_DIR )
diff --git a/cmake/FindAllegro5TTF.cmake b/cmake/FindAllegro5TTF.cmake
index 3ae23a2..418b2ce 100644
--- a/cmake/FindAllegro5TTF.cmake
+++ b/cmake/FindAllegro5TTF.cmake
@@ -17,6 +17,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALLEGRO5_TTF DEFAULT_MSG ALLEGRO5_TTF_LIBRARY
 
 IF(ALLEGRO5_TTF_FOUND)
   SET(ALLEGRO5_TTF_LIBRARIES ${ALLEGRO5_TTF_LIBRARY})
+  SET(ALLEGRO5_LIBS ${ALLEGRO5_LIBS} ${ALLEGRO5_TTF_LIBRARIES})
 ENDIF(ALLEGRO5_TTF_FOUND)
 
 MARK_AS_ADVANCED(ALLEGRO5_TTF_LIBRARY ALLEGRO5_TTF_INCLUDE_DIR )
diff --git a/cmake/android.toolchain b/cmake/android.toolchain
index 294e3d1..9d96dc2 100644
--- a/cmake/android.toolchain
+++ b/cmake/android.toolchain
@@ -4,6 +4,13 @@ SET(CMAKE_SYSTEM_VERSION 1)
 
 #set path for android toolchain -- look
 
+set(ANDROID_ALLEGRO_ROOT "$ENV{ANDROID_ALLEGRO_ROOT}" CACHE PATH "Path to Allegro 5 source directory after being compiled for Android" )
+
+message( STATUS "Selected Allegro dir: ${ANDROID_ALLEGRO_ROOT}" )
+if(NOT EXISTS ${ANDROID_ALLEGRO_ROOT})
+   message( FATAL_ERROR "Invalid ANDROID_ALLEGRO_ROOT! Point it to directory with Allegro 5 source after compiling it for Android.")
+endif()
+
 set(ANDROID_NDK_TOOLCHAIN_ROOT "$ENV{ANDROID_NDK_TOOLCHAIN_ROOT}" CACHE PATH "Path to the Android NDK Standalone Toolchain" )
 
 message( STATUS "Selected Android toolchain: ${ANDROID_NDK_TOOLCHAIN_ROOT}" )
@@ -70,7 +77,7 @@ set(CMAKE_RANLIB
 
 set_property(CACHE ARM_TARGETS PROPERTY STRINGS ${PossibleArmTargets} )
 
-set(LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH 
+set(LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR}/android CACHE PATH
     "root for library output, set this to change where
     android libs are installed to")
     
@@ -150,6 +157,21 @@ endif()
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
 
+find_program(ANDROID_TOOL android NAMES android android.bat CMAKE_FIND_ROOT_PATH_BOTH)
+find_program(NDK_BUILD ndk-build CMAKE_FIND_ROOT_PATH_BOTH)
+find_program(ANT ant CMAKE_FIND_ROOT_PATH_BOTH)
+set(ANT_COMMAND "${ANT}" -noinput -nouserlib -noclasspath -quiet)
+
+if(NOT ANDROID_TOOL)
+    message(FATAL_ERROR "android tool not found")
+endif()
+if(NOT NDK_BUILD)
+    message(FATAL_ERROR "ndk-build not found")
+endif()
+if(NOT ANT)
+    message(FATAL_ERROR "ant not found")
+endif()
+
 #set these global flags for cmake client scripts to change behavior
 set(ANDROID True)
 set(BUILD_ANDROID True)
diff --git a/cmake/libsuperderpy.cmake b/cmake/libsuperderpy.cmake
index 8c8dc73..38c3a6c 100644
--- a/cmake/libsuperderpy.cmake
+++ b/cmake/libsuperderpy.cmake
@@ -65,6 +65,10 @@ MACRO(register_gamestate name)
 
     install(TARGETS "libsuperderpy-${LIBSUPERDERPY_GAMENAME}-${name}" DESTINATION ${LIB_INSTALL_DIR})
 
+    if (ANDROID)
+	add_dependencies(${LIBSUPERDERPY_GAMENAME}_apk "libsuperderpy-${LIBSUPERDERPY_GAMENAME}-${name}")
+    endif()
+
 ENDMACRO()
 
 MACRO(libsuperderpy_copy EXECUTABLE)
@@ -77,6 +81,88 @@ ENDMACRO()
 
 include(InstallRequiredSystemLibraries)
 
+if(LIBSUPERDERPY_GAMENAME)
+    configure_file("${CMAKE_SOURCE_DIR}/libsuperderpy/src/defines.h.in" "${CMAKE_SOURCE_DIR}/src/defines.h")
+endif(LIBSUPERDERPY_GAMENAME)
+
+MACRO(add_libsuperderpy_target EXECUTABLE_SRC_LIST)
+    if(ANDROID)
+	set(EXECUTABLE game)
+	add_library(${EXECUTABLE} SHARED ${EXECUTABLE_SRC_LIST})
+
+	set(APK_PATH ${CMAKE_BINARY_DIR}/android/bin/${LIBSUPERDERPY_GAMENAME}-debug.apk)
+
+	add_custom_target(${LIBSUPERDERPY_GAMENAME}_apk ALL
+	    DEPENDS ${EXECUTABLE}
+	    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/android"
+	    COMMAND ${ANT_COMMAND} debug
+	)
+
+        add_custom_target(install_apk
+	    DEPENDS ${LIBSUPERDERPY_GAMENAME}_apk
+	    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/android"
+	    COMMAND adb -d install -r ${APK_PATH}
+	)
+
+        add_custom_target(run_apk
+	    DEPENDS install_apk
+	    COMMAND adb -d shell
+	            'am start -a android.intent.action.MAIN -n net.dosowisko.${LIBSUPERDERPY_GAMENAME}/.SuperDerpyActivity'
+	    )
+
+    else(ANDROID)
+	add_executable(${EXECUTABLE} WIN32 MACOSX_BUNDLE ${EXECUTABLE_SRC_LIST})
+    endif(ANDROID)
+ENDMACRO()
+
+if(ANDROID)
+    set(ANDROID_TARGET "android-15" CACHE STRING "What Android target to compile for.")
+
+    # The android tool on Windows is a batch file wrapper, which cannot be
+    # started by MSYS shell directly. We invoke it via cmd.exe instead.
+    # We don't use the full path to avoid problems with spaces,
+    # and hope that android.bat is somewhere on the PATH.
+    if(ANDROID_TOOL MATCHES "[.]bat$")
+	set(ANDROID_UPDATE_COMMAND
+	    cmd.exe /c "android.bat update project -p . -t ${ANDROID_TARGET}")
+    else()
+	set(ANDROID_UPDATE_COMMAND
+	    "${ANDROID_TOOL}" update project -p . -t ${ANDROID_TARGET})
+    endif()
+
+    file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/android")
+    file(COPY "${CMAKE_SOURCE_DIR}/libsuperderpy/android" DESTINATION "${CMAKE_BINARY_DIR}")
+
+    MACRO(configure_android_file PATH)
+        configure_file("${CMAKE_BINARY_DIR}/android/${PATH}.in" "${CMAKE_BINARY_DIR}/android/${PATH}" ${ARGN})
+	file(REMOVE "${CMAKE_BINARY_DIR}/android/${PATH}.in")
+    ENDMACRO()
+
+    configure_android_file("AndroidManifest.xml")
+    configure_android_file("localgen.properties")
+    configure_android_file("build.xml" @ONLY)
+    configure_android_file("project.properties" @ONLY)
+    configure_android_file("res/values/strings.xml")
+    configure_android_file("jni/localgen.mk")
+    if (ALLEGRO5_LIBRARIES MATCHES "^.*-debug$")
+	configure_file("${CMAKE_BINARY_DIR}/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.debug.in" "${CMAKE_BINARY_DIR}/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java")
+    else()
+	configure_file("${CMAKE_BINARY_DIR}/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.in" "${CMAKE_BINARY_DIR}/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java")
+    endif()
+    file(REMOVE "${CMAKE_BINARY_DIR}/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.in")
+    file(REMOVE "${CMAKE_BINARY_DIR}/android/src/net/dosowisko/libsuperderpy/SuperDerpyActivity.java.debug.in")
+
+    file(RENAME "${CMAKE_BINARY_DIR}/android/src/net/dosowisko/libsuperderpy" "${CMAKE_BINARY_DIR}/android/src/net/dosowisko/${LIBSUPERDERPY_GAMENAME}")
+
+    file(COPY ${ALLEGRO5_LIBS} DESTINATION ${LIBRARY_OUTPUT_PATH})
+    file(COPY "${ANDROID_ALLEGRO_ROOT}/android/libs/${ARM_TARGETS}/Allegro5.jar" DESTINATION ${LIBRARY_OUTPUT_PATH})
+
+    file(COPY "${CMAKE_SOURCE_DIR}/data/" DESTINATION "${CMAKE_BINARY_DIR}/android/assets/")
+
+    execute_process(COMMAND ${ANDROID_UPDATE_COMMAND} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/android")
+
+endif(ANDROID)
+
 set(LIBSUPERDERPY_CONFIG_INCLUDED 1)
 
 endif (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
diff --git a/src/defines.h.in b/src/defines.h.in
new file mode 100644
index 0000000..15575d5
--- /dev/null
+++ b/src/defines.h.in
@@ -0,0 +1,10 @@
+#ifndef DEFINES_H
+#define DEFINES_H
+
+/*
+ * These values are automatically set according to their cmake variables.
+ */
+#define LIBSUPERDERPY_GAMENAME "${LIBSUPERDERPY_GAMENAME}"
+#define LIBSUPERDERPY_GAMENAME_PRETTY "${LIBSUPERDERPY_GAMENAME_PRETTY}"
+
+#endif /* DEFINES_H */
diff --git a/src/libsuperderpy.c b/src/libsuperderpy.c
index 8b5f8b0..e7ab1d4 100644
--- a/src/libsuperderpy.c
+++ b/src/libsuperderpy.c
@@ -418,6 +418,8 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
 			}
 #ifdef ALLEGRO_MACOSX
 			else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == 104)) { //TODO: report to upstream
+#elif defined(ALLEGRO_ANDROID)
+			else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == ALLEGRO_KEY_MENU)) {
 #else
 			else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == ALLEGRO_KEY_TILDE)) {
 #endif