From 1cc40c0a7c260f0562572bc99f39a666a12f1b09 Mon Sep 17 00:00:00 2001 From: sapier Date: Mon, 21 Apr 2014 14:10:59 +0200 Subject: Add support for Android 2.3+ There have been plenty of ppl involved in creating this version. I don't wanna mention names as I'm sure I'd forget someone so I just tell where help has been done: - The partial android versions done by various ppl - Testing on different android devices - reviewing code (especially the in core changes) - testing controls - reviewing texts A big thank you to everyone helping this to be completed! --- build/android/AndroidManifest.xml.template | 35 + build/android/Makefile | 724 +++++++++++++++++++++ build/android/build.xml | 16 + build/android/irrlicht-back_button.patch | 19 + build/android/irrlicht-texturehack.patch | 240 +++++++ build/android/irrlicht-touchcount.patch | 30 + build/android/jni/Android.mk | 310 +++++++++ build/android/jni/Application.mk | 8 + build/android/libvorbis-libogg-fpu.patch | 37 ++ build/android/project.properties | 1 + build/android/res/drawable-hdpi/irr_icon.png | Bin 0 -> 5490 bytes build/android/res/drawable-ldpi/irr_icon.png | Bin 0 -> 2262 bytes build/android/res/drawable-mdpi/irr_icon.png | Bin 0 -> 3110 bytes build/android/res/drawable-xhdpi/irr_icon.png | Bin 0 -> 7610 bytes build/android/res/layout/assetcopy.xml | 22 + build/android/res/values/styles.xml | 11 + .../org/minetest/minetest/MinetestAssetCopy.java | 288 ++++++++ .../org/minetest/minetest/MinetestTextEntry.java | 91 +++ .../org/minetest/minetest/MtNativeActivity.java | 93 +++ 19 files changed, 1925 insertions(+) create mode 100644 build/android/AndroidManifest.xml.template create mode 100644 build/android/Makefile create mode 100644 build/android/build.xml create mode 100644 build/android/irrlicht-back_button.patch create mode 100644 build/android/irrlicht-texturehack.patch create mode 100644 build/android/irrlicht-touchcount.patch create mode 100644 build/android/jni/Android.mk create mode 100644 build/android/jni/Application.mk create mode 100644 build/android/libvorbis-libogg-fpu.patch create mode 100644 build/android/project.properties create mode 100644 build/android/res/drawable-hdpi/irr_icon.png create mode 100644 build/android/res/drawable-ldpi/irr_icon.png create mode 100644 build/android/res/drawable-mdpi/irr_icon.png create mode 100644 build/android/res/drawable-xhdpi/irr_icon.png create mode 100644 build/android/res/layout/assetcopy.xml create mode 100644 build/android/res/values/styles.xml create mode 100644 build/android/src/org/minetest/minetest/MinetestAssetCopy.java create mode 100644 build/android/src/org/minetest/minetest/MinetestTextEntry.java create mode 100644 build/android/src/org/minetest/minetest/MtNativeActivity.java (limited to 'build/android') diff --git a/build/android/AndroidManifest.xml.template b/build/android/AndroidManifest.xml.template new file mode 100644 index 000000000..dcffa35f6 --- /dev/null +++ b/build/android/AndroidManifest.xml.template @@ -0,0 +1,35 @@ + + + + + + + + ###DEBUG_BUILD### + + + + + + + + + + + + + + diff --git a/build/android/Makefile b/build/android/Makefile new file mode 100644 index 000000000..9e693432b --- /dev/null +++ b/build/android/Makefile @@ -0,0 +1,724 @@ +# build options + +OS := $(shell uname) + +#automaticaly set number of jobs +ifeq ($(OS),Linux) + PARALLEL := $(shell grep -c ^processor /proc/cpuinfo) +else + PARALLEL := 1 +endif + +# compile with GPROF +# GPROF = 1 + +# build for build platform +APP_PLATFORM = android-9 + +# paths used for timestaps, dependencys, tree config and libs +PATHCFGFILE = path.cfg + +ROOT = $(shell pwd) + +################################################################################ +# Android Version code +# Increase for each build! +################################################################################ +ANDROID_VERSION_CODE = 3 + +################################################################################ +# toolchain config for arm old processors +################################################################################ +TARGET_HOST = arm-linux +TARGET_ABI = armeabi +TARGET_LIBDIR = armeabi +TARGET_TOOLCHAIN = arm-linux-androideabi- +TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfp +CROSS_PREFIX = arm-linux-androideabi- +COMPILER_VERSION = 4.8 + +################################################################################ +# toolchain config for arm new processors +################################################################################ +#TARGET_HOST = arm-linux +#TARGET_ABI = armeabi-v7a-hard +#TARGET_LIBDIR = armeabi-v7a +#TARGET_TOOLCHAIN = arm-linux-androideabi- +#TARGET_CFLAGS_ADDON = -mfpu=vfpv3-d16 -D_NDK_MATH_NO_SOFTFP=1 \ +# -mfloat-abi=hard -march=armv7-a +#TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON) +#TARGET_LDFLAGS_ADDON = -Wl,--no-warn-mismatch -lm_hard +#CROSS_PREFIX = arm-linux-androideabi- +#COMPILER_VERSION = 4.8 + +################################################################################ +# toolchain config for little endian mips +################################################################################ +#TARGET_HOST = mipsel-linux +#TARGET_ABI = mips +#TARGET_LIBDIR = mips +#TARGET_TOOLCHAIN = mipsel-linux-android- +#CROSS_PREFIX = mipsel-linux-android- +#COMPILER_VERSION = 4.8 + +################################################################################ +# toolchain config for x86 +################################################################################ +#TARGET_HOST = x86-linux +#TARGET_ABI = x86 +#TARGET_LIBDIR = x86 +#TARGET_TOOLCHAIN = x86- +#CROSS_PREFIX = i686-linux-android- +#COMPILER_VERSION = 4.8 + +################################################################################ +ASSETS_TIMESTAMP = deps/assets_timestamp + +LEVELDB_DIR = $(ROOT)/deps/leveldb/ +LEVELDB_LIB = $(LEVELDB_DIR)libleveldb.a +LEVELDB_TIMESTAMP = $(LEVELDB_DIR)/timestamp +LEVELDB_TIMESTAMP_INT = $(ROOT)/deps/leveldb_timestamp +LEVELDB_URL_GIT = https://code.google.com/p/leveldb/ + +OPENAL_DIR = $(ROOT)/deps/openal-soft/ +OPENAL_LIB = $(OPENAL_DIR)libs/$(TARGET_ABI)/libopenal.so +OPENAL_TIMESTAMP = $(OPENAL_DIR)/timestamp +OPENAL_TIMESTAMP_INT = $(ROOT)/deps/openal_timestamp +OPENAL_URL_GIT = https://github.com/apportable/openal-soft + +OGG_DIR = $(ROOT)/deps/libvorbis-libogg-android/ +OGG_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so +VORBIS_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so +OGG_TIMESTAMP = $(OGG_DIR)timestamp +OGG_TIMESTAMP_INT = $(ROOT)/deps/ogg_timestamp +OGG_URL_GIT = https://github.com/vincentjames501/libvorbis-libogg-android + +IRRLICHT_DIR = $(ROOT)/deps/irrlicht/ +IRRLICHT_LIB = $(IRRLICHT_DIR)lib/Android/libIrrlicht.a +IRRLICHT_TIMESTAMP = $(IRRLICHT_DIR)timestamp +IRRLICHT_TIMESTAMP_INT = $(ROOT)/deps/irrlicht_timestamp +IRRLICHT_URL_SVN = http://svn.code.sf.net/p/irrlicht/code/branches/ogl-es/ + +OPENSSL_BASEDIR = openssl-android +OPENSSL_DIR = $(ROOT)/deps/$(OPENSSL_BASEDIR)/ +OPENSSL_LIB = $(OPENSSL_DIR)libs/$(TARGET_ABI)/libopenssl.so +OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp +OPENSSL_TIMESTAMP_INT = $(ROOT)/deps/openssl_timestamp +OPENSSL_URL_GIT = https://github.com/wobbals/openssl-android + +CURL_VERSION = 7.35.0 +CURL_DIR = $(ROOT)/deps/curl-$(CURL_VERSION) +CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a +CURL_TIMESTAMP = $(CURL_DIR)/timestamp +CURL_TIMESTAMP_INT = $(ROOT)/deps/curl_timestamp +CURL_URL_HTTP = http://curl.haxx.se/download/curl-${CURL_VERSION}.tar.bz2 + +FREETYPE_DIR = $(ROOT)/deps/freetype2-android/ +FREETYPE_LIB = $(FREETYPE_DIR)/Android/obj/local/$(TARGER_ABI)/libfreetype2-static.a +FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp +FREETYPE_TIMESTAMP_INT = $(ROOT)/deps/freetype_timestamp +FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android + +-include $(PATHCFGFILE) + +.PHONY : debug release reconfig delconfig \ + leveldb_download clean_leveldb leveldb\ + irrlicht_download clean_irrlicht irrlicht \ + clean_assets assets \ + freetype_download clean_freetype freetype \ + apk clean_apk \ + clean_all clean prep_srcdir \ + install_debug install envpaths all \ + manifest clean_manifest\ + $(ASSETS_TIMESTAMP) $(LEVELDB_TIMESTAMP) \ + $(OPENAL_TIMESTAMP) $(OGG_TIMESTAMP) \ + $(IRRLICHT_TIMESTAMP) $(CURL_TIMESTAMP) \ + $(OPENSSL_TIMESTAMP) curl_binary \ + $(ROOT)/jni/src/android_version.h + +debug : $(PATHCFGFILE) + export NDEBUG=; \ + export BUILD_TYPE=debug; \ + $(MAKE) -j${PARALLEL} apk + +all : debug release + +release : $(PATHCFGFILE) + @export NDEBUG=1; \ + export BUILD_TYPE=release; \ + $(MAKE) -j${PARALLEL} apk + +reconfig: delconfig + @$(MAKE) -j${PARALLEL} $(PATHCFGFILE) + +delconfig : + $(RM) ${PATHCFGFILE} + +$(PATHCFGFILE) : + @echo "Please specify path of ANDROID NDK"; \ + echo "e.g. /home/user/android-ndk-r9c/"; \ + read ANDROID_NDK ; \ + if [ ! -d $$ANDROID_NDK ] ; then \ + echo "$$ANDROID_NDK is not a valid folder"; \ + exit 1; \ + fi; \ + echo "ANDROID_NDK = $$ANDROID_NDK" > ${PATHCFGFILE}; \ + echo "NDK_MODULE_PATH = $$ANDROID_NDK/tools" >> ${PATHCFGFILE}; \ + echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";\ + echo "+ Note: NDK_MODULE_PATH is set to $$ANDROID_NDK/tools"; \ + echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";\ + echo "Please specify path of ANDROID SDK"; \ + echo "e.g. /home/user/adt-bundle-linux-x86_64-20131030/sdk/"; \ + read SDKFLDR ; \ + if [ ! -d $$SDKFLDR ] ; then \ + echo "$$SDKFLDR is not a valid folder"; \ + exit 1; \ + fi; \ + echo "SDKFOLDER = $$SDKFLDR" >> ${PATHCFGFILE}; + +$(OPENAL_TIMESTAMP) : openal_download + @LAST_MODIF=$$(find ${OPENAL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${OPENAL_TIMESTAMP}; \ + fi + +openal_download : + @if [ ! -d ${OPENAL_DIR} ] ; then \ + echo "openal sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd ${ROOT}/deps ; \ + git clone ${OPENAL_URL_GIT} || exit 1; \ + fi + +openal : $(OPENAL_LIB) + +$(OPENAL_LIB): $(OPENAL_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${OPENAL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${OPENAL_TIMESTAMP} -nt ${OPENAL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for openal detected building..."; \ + cd ${OPENAL_DIR}; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${OPENAL_TIMESTAMP}; \ + touch ${OPENAL_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for openal"; \ + fi + +clean_openal : + $(RM) -rf ${OPENAL_DIR} + +$(OGG_TIMESTAMP) : ogg_download + @LAST_MODIF=$$(find ${OGG_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${OGG_TIMESTAMP}; \ + fi + +ogg_download : + @if [ ! -d ${OGG_DIR} ] ; then \ + echo "ogg sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd ${ROOT}/deps ; \ + git clone ${OGG_URL_GIT}|| exit 1; \ + cd libvorbis-libogg-android ; \ + patch -p1 < ../../libvorbis-libogg-fpu.patch || exit 1; \ + fi + +ogg : $(OGG_LIB) + +$(OGG_LIB): $(OGG_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${OGG_TIMESTAMP_INT} ] ; then \ + echo "${OGG_TIMESTAMP_INT} doesn't exist"; \ + REFRESH=1; \ + fi; \ + if [ ${OGG_TIMESTAMP} -nt ${OGG_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for ogg detected building..."; \ + cd ${OGG_DIR}; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${OGG_TIMESTAMP}; \ + touch ${OGG_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for libogg/libvorbis"; \ + fi + +clean_ogg : + $(RM) -rf ${OGG_DIR} + +$(OPENSSL_TIMESTAMP) : openssl_download + @LAST_MODIF=$$(find ${OPENSSL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${OPENSSL_TIMESTAMP}; \ + fi + +openssl_download : + @if [ ! -d ${OPENSSL_DIR} ] ; then \ + echo "openssl sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd ${ROOT}/deps ; \ + git clone ${OPENSSL_URL_GIT} || exit 1; \ + fi + +openssl : $(OPENSSL_LIB) + +$(OPENSSL_LIB): $(OPENSSL_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${OPENSSL_TIMESTAMP_INT} ] ; then \ + echo "${OPENSSL_TIMESTAMP_INT} doesn't exist"; \ + REFRESH=1; \ + fi; \ + if [ ${OPENSSL_TIMESTAMP} -nt ${OPENSSL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for openssl detected building..."; \ + cd ${OPENSSL_DIR}; \ + cat jni/Application.mk | grep -v NDK_TOOLCHAIN_VERSION >jni/Application.mk.new;\ + mv jni/Application.mk.new jni/Application.mk; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${OPENSSL_TIMESTAMP}; \ + touch ${OPENSSL_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for openssl"; \ + fi + +clean_openssl : + $(RM) -rf ${OPENSSL_DIR} + +$(LEVELDB_TIMESTAMP) : leveldb_download + @LAST_MODIF=$$(find ${LEVELDB_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${LEVELDB_TIMESTAMP}; \ + fi + +leveldb_download : + @if [ ! -d ${LEVELDB_DIR} ] ; then \ + echo "leveldb sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd ${ROOT}/deps ; \ + git clone ${LEVELDB_URL_GIT} || exit 1; \ + fi + +leveldb : $(LEVELDB_LIB) + +$(LEVELDB_LIB): $(LEVELDB_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${LEVELDB_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${LEVELDB_TIMESTAMP} -nt ${LEVELDB_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + export PATH=$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for leveldb detected building..."; \ + cd deps/leveldb; \ + export CROSS_PREFIX=${CROSS_PREFIX}; \ + export TOOLCHAIN=/tmp/ndk-arm; \ + ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ + --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ + --install-dir=$${TOOLCHAIN} --system=linux-x86_64; \ + export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ + export CC=${CROSS_PREFIX}gcc; \ + export CXX=${CROSS_PREFIX}g++; \ + export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ + export CPPFLAGS="$${CPPFLAGS} ${TARGET_CFLAGS_ADDON}"; \ + export LDFLAGS="$${LDFLAGS} ${TARGET_LDFLAGS_ADDON}"; \ + export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ + $(MAKE) -j${PARALLEL} -s || exit 1; \ + touch ${LEVELDB_TIMESTAMP}; \ + touch ${LEVELDB_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for leveldb"; \ + fi + +clean_leveldb : + $(RM) -rf deps/leveldb + +$(FREETYPE_TIMESTAMP) : freetype_download + @LAST_MODIF=$$(find ${FREETYPE_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${FREETYPE_TIMESTAMP}; \ + fi + +freetype_download : + @if [ ! -d ${FREETYPE_DIR} ] ; then \ + echo "freetype sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd deps; \ + git clone ${FREETYPE_URL_GIT} || exit 1; \ + fi + +$(IRRLICHT_TIMESTAMP) : irrlicht_download + @LAST_MODIF=$$(find ${IRRLICHT_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${IRRLICHT_TIMESTAMP}; \ + fi + +freetype : $(FREETYPE_LIB) + +$(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${FREETYPE_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ! -e ${FREETYPE_LIB} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${FREETYPE_TIMESTAMP} -nt ${FREETYPE_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + mkdir -p ${FREETYPE_DIR}; \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for freetype detected building..."; \ + cd ${FREETYPE_DIR}/Android/jni; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_PLATFORM=${APP_PLATFORM} APP_ABI=${TARGET_ABI} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${FREETYPE_TIMESTAMP}; \ + touch ${FREETYPE_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for freetype"; \ + fi + +clean_freetype : + $(RM) -rf ${FREETYPE_DIR} + +#Note: Texturehack patch is required for gpu's not supporting color format +# correctly. Known bad GPU: +# -geforce on emulator +# -Vivante Corporation GC1000 core (e.g. Galaxy Tab 3) + +irrlicht_download : + @if [ ! -d "deps/irrlicht" ] ; then \ + echo "irrlicht sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd deps; \ + svn co ${IRRLICHT_URL_SVN} irrlicht || exit 1; \ + cd irrlicht; \ + patch -p1 < ../../irrlicht-touchcount.patch || exit 1; \ + patch -p1 < ../../irrlicht-back_button.patch || exit 1; \ + patch -p1 < ../../irrlicht-texturehack.patch || exit 1; \ + fi + +irrlicht : $(IRRLICHT_LIB) + +$(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB) + @REFRESH=0; \ + if [ ! -e ${IRRLICHT_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ! -e ${IRRLICHT_LIB} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${IRRLICHT_TIMESTAMP} -nt ${IRRLICHT_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + mkdir -p ${IRRLICHT_DIR}; \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for irrlicht detected building..."; \ + cd deps/irrlicht/source/Irrlicht/Android; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${IRRLICHT_TIMESTAMP}; \ + touch ${IRRLICHT_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for irrlicht"; \ + fi + +clean_irrlicht : + $(RM) -rf deps/irrlicht + +$(CURL_TIMESTAMP) : curl_download + @LAST_MODIF=$$(find ${CURL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${CURL_TIMESTAMP}; \ + fi + +curl_download : + @if [ ! -d "deps/curl-${CURL_VERSION}" ] ; then \ + echo "curl sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd deps; \ + wget ${CURL_URL_HTTP} || exit 1; \ + tar -xjf curl-${CURL_VERSION}.tar.bz2 || exit 1; \ + rm curl-${CURL_VERSION}.tar.bz2; \ + fi + +curl : $(CURL_LIB) + +$(CURL_LIB): $(CURL_TIMESTAMP) $(OPENSSL_LIB) + @REFRESH=0; \ + if [ ! -e ${CURL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ! -e ${CURL_LIB} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${CURL_TIMESTAMP} -nt ${CURL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + mkdir -p ${CURL_DIR}; \ + export PATH="$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}"; \ + echo "changed timestamp for curl detected building..."; \ + cd deps/curl-${CURL_VERSION}; \ + export CROSS_PREFIX=${CROSS_PREFIX}; \ + export TOOLCHAIN=/tmp/ndk-arm; \ + ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ + --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ + --install-dir=$${TOOLCHAIN} --system=linux-x86_64; \ + export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ + export CC=${CROSS_PREFIX}gcc; \ + export CXX=${CROSS_PREFIX}g++; \ + export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ + export CPPFLAGS="$${CPPFLAGS} -I${OPENSSL_DIR}/include \ + -L${OPENSSL_DIR}/libs/${TARGET_ABI}/ ${TARGET_CFLAGS_ADDON}"; \ + export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ + export LDFLAGS="$${LDFLAGS} -L${OPENSSL_DIR}/libs/${TARGET_ABI}/ \ + ${TARGET_LDFLAGS_ADDON}"; \ + ./configure --host=${TARGET_HOST} --disable-shared --enable-static --with-ssl; \ + $(MAKE) -j${PARALLEL} -s || exit 1; \ + touch ${CURL_TIMESTAMP}; \ + touch ${CURL_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for curl"; \ + fi + +clean_curl : + $(RM) -rf deps/curl-${CURL_VERSION} + + +curl_binary: + @if [ ! -d "deps/curl-${CURL_VERSION_BINARY}" ] ; then \ + echo "curl sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd deps; \ + wget http://curl.haxx.se/gknw.net/7.34.0/dist-android/curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\ + tar -xzf curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\ + mv curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android curl-${CURL_VERSION_BINARY};\ + rm curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz; \ + fi + +$(ASSETS_TIMESTAMP) : $(IRRLICHT_LIB) + @mkdir -p ${ROOT}/deps; \ + LAST_MODIF=$$(find ${ROOT}/../../builtin -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../builtin/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + echo builtin changed $$LAST_MODIF; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../client -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../client/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../doc -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../doc/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../fonts -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../fonts/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../games -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../games/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../mods -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../mods/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../po -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../po/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../textures -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../textures/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${IRRLICHT_DIR}/media -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${IRRLICHT_DIR}/media/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + if [ ${ROOT}/../../minetest.conf.example -nt ${ASSETS_TIMESTAMP} ] ; then \ + echo "conf changed"; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + if [ ${ROOT}/../../README.txt -nt ${ASSETS_TIMESTAMP} ] ; then \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + if [ ! -e $(ASSETS_TIMESTAMP) ] ; then \ + touch $(ASSETS_TIMESTAMP); \ + fi + +assets : $(ASSETS_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${ASSETS_TIMESTAMP}.old ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${ASSETS_TIMESTAMP} -nt ${ASSETS_TIMESTAMP}.old ] ; then \ + REFRESH=1; \ + fi; \ + if [ ! -d ${ROOT}/assets ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + echo "assets changed, refreshing..."; \ + $(MAKE) -j${PARALLEL} clean_assets; \ + mkdir -p ${ROOT}/assets/Minetest; \ + cp ${ROOT}/../../minetest.conf.example ${ROOT}/assets/Minetest; \ + cp ${ROOT}/../../README.txt ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../builtin ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../client ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../doc ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../fonts ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../games ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../mods ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../po ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../textures ${ROOT}/assets/Minetest; \ + mkdir -p ${ROOT}/assets/Minetest/media; \ + cp -r ${IRRLICHT_DIR}/media/Shaders ${ROOT}/assets/Minetest/media; \ + cd ${ROOT}/assets; \ + find . -name "timestamp" -exec rm {} \; ; \ + find . -name "*.blend" -exec rm {} \; ; \ + ls -R | grep ":$$" | sed -e 's/:$$//' -e 's/\.//' -e 's/^\///' > "index.txt"; \ + cp ${ROOT}/${ASSETS_TIMESTAMP} ${ROOT}/${ASSETS_TIMESTAMP}.old; \ + else \ + echo "nothing to be done for assets"; \ + fi + +clean_assets : + @$(RM) -r assets + +apk: $(PATHCFGFILE) assets $(IRRLICHT_LIB) $(CURL_LIB) \ + $(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ROOT)/jni/src/android_version.h + @export NDEBUG=$$NDEBUG; $(MAKE) -j${PARALLEL} manifest; \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + export ANDROID_HOME=${SDKFOLDER}; \ + mkdir -p ${ROOT}/src; \ + ndk-build NDK_MODULE_PATH=${NDK_MODULE_PATH} -j${PARALLEL} \ + GPROF=${GPROF} APP_ABI=${TARGET_ABI} \ + APP_PLATFORM=${APP_PLATFORM} \ + TARGET_LIBDIR=${TARGET_LIBDIR} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" && \ + ant $$BUILD_TYPE && \ + echo "++ Success!" && \ + echo "APK: bin/Minetest-$$BUILD_TYPE.apk" && \ + echo "You can install it with \`adb install -r bin/Minetest-$$BUILD_TYPE.apk\`" + +prep_srcdir : + @rm ${ROOT}/jni/src; \ + ln -s ${ROOT}/../../src ${ROOT}/jni/src + +clean_apk : manifest + @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ + export ANDROID_HOME=${SDKFOLDER}; \ + ant clean + +install_debug : + @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ + adb install -r ${ROOT}/bin/Minetest-debug.apk + +install : + @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ + adb install -r ${ROOT}/bin/Minetest-release.apk + +envpaths : + @echo "export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}" > and_env;\ + echo "export ANDROID_HOME=${SDKFOLDER}" >> and_env; + +clean_all : + @$(MAKE) -j${PARALLEL} clean_apk; \ + $(MAKE) clean_assets clean_irrlicht clean_leveldb clean_curl clean_openssl \ + clean_openal clean_ogg clean_manifest; \ + sleep 1; \ + $(RM) -r gen libs obj deps bin Debug and_env + +$(ROOT)/jni/src/android_version.h : + @echo "#define STR_HELPER(x) #x" \ + >${ROOT}/jni/src/android_version.h; \ + echo "#define STR(x) STR_HELPER(x)" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define VERSION_MAJOR $$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | awk '{print $$2;}')" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define VERSION_MINOR $$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | awk '{print $$2;}')" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define VERSION_PATCH $$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}')" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define VERSION_PATCH_ORIG $$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}')" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define CMAKE_VERSION_GITHASH \"$$(git rev-parse --short=8 HEAD)\"" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define CMAKE_VERSION_STRING STR(VERSION_MAJOR)\".\"STR(VERSION_MINOR)\ + \".\"STR(VERSION_PATCH)" \ + >> ${ROOT}/jni/src/android_version.h; + +manifest : + @VERS_MAJOR=$$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | awk '{print $$2;}'); \ + VERS_MINOR=$$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | awk '{print $$2;}'); \ + VERS_PATCH=$$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}'); \ + BASE_VERSION="$$VERS_MAJOR.$$VERS_MINOR.$$VERS_PATCH"; \ + if [ "${NDEBUG}x" != "x" ] ; then \ + DBG=''; \ + DBG_FLAG="android:debuggable=\"false\""; \ + else \ + DBG=""; \ + DBG_FLAG="android:debuggable=\"true\""; \ + fi; \ + cat ${ROOT}/AndroidManifest.xml.template | \ + sed s/###ANDROID_VERSION###/${ANDROID_VERSION_CODE}/g | \ + sed s/###BASE_VERSION###/$$BASE_VERSION/g | \ + sed -e "s@###DEBUG_BUILD###@$$DBG@g" | \ + sed -e "s@###DEBUG_FLAG###@$$DBG_FLAG@g" >${ROOT}/AndroidManifest.xml + +clean_manifest : + rm -rf ${ROOT}/AndroidManifest.xml + +clean : clean_apk clean_assets diff --git a/build/android/build.xml b/build/android/build.xml new file mode 100644 index 000000000..50a3e95ac --- /dev/null +++ b/build/android/build.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/build/android/irrlicht-back_button.patch b/build/android/irrlicht-back_button.patch new file mode 100644 index 000000000..227749ba7 --- /dev/null +++ b/build/android/irrlicht-back_button.patch @@ -0,0 +1,19 @@ +--- irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 20:56:21.289559503 +0200 ++++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp.orig 2014-06-03 20:57:39.281556749 +0200 +@@ -423,6 +423,7 @@ + } + + device->postEventFromUser(event); ++ status = 1; + } + break; + default: +@@ -479,7 +480,7 @@ + KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT + KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT + KeyMap[3] = KEY_HOME; // AKEYCODE_HOME +- KeyMap[4] = KEY_BACK; // AKEYCODE_BACK ++ KeyMap[4] = KEY_CANCEL; // AKEYCODE_BACK + KeyMap[5] = KEY_UNKNOWN; // AKEYCODE_CALL + KeyMap[6] = KEY_UNKNOWN; // AKEYCODE_ENDCALL + KeyMap[7] = KEY_KEY_0; // AKEYCODE_0 diff --git a/build/android/irrlicht-texturehack.patch b/build/android/irrlicht-texturehack.patch new file mode 100644 index 000000000..a458ede72 --- /dev/null +++ b/build/android/irrlicht-texturehack.patch @@ -0,0 +1,240 @@ +--- irrlicht/source/Irrlicht/COGLESTexture.cpp.orig 2014-06-22 17:01:13.266568869 +0200 ++++ irrlicht/source/Irrlicht/COGLESTexture.cpp 2014-06-22 17:03:59.298572810 +0200 +@@ -366,112 +366,140 @@ + void(*convert)(const void*, s32, void*) = 0; + getFormatParameters(ColorFormat, InternalFormat, filtering, PixelFormat, PixelType, convert); + +- // make sure we don't change the internal format of existing images +- if (!newTexture) +- InternalFormat = oldInternalFormat; +- +- Driver->setActiveTexture(0, this); +- +- if (Driver->testGLError()) +- os::Printer::log("Could not bind Texture", ELL_ERROR); +- +- // mipmap handling for main texture +- if (!level && newTexture) +- { +- // auto generate if possible and no mipmap data is given +- if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) +- { +- if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) +- glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); +- else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) +- glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); +- else +- glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); ++ bool retry = false; ++ ++ do { ++ if (retry) { ++ InternalFormat = GL_RGBA; ++ PixelFormat = GL_RGBA; ++ convert = CColorConverter::convert_A8R8G8B8toA8B8G8R8; ++ } ++ // make sure we don't change the internal format of existing images ++ if (!newTexture) ++ InternalFormat = oldInternalFormat; + +- glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); +- AutomaticMipmapUpdate=true; +- } ++ Driver->setActiveTexture(0, this); + +- // enable bilinear filter without mipmaps +- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); +- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); +- } ++ if (Driver->testGLError()) ++ os::Printer::log("Could not bind Texture", ELL_ERROR); + +- // now get image data and upload to GPU ++ // mipmap handling for main texture ++ if (!level && newTexture) ++ { ++ // auto generate if possible and no mipmap data is given ++ if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) ++ { ++ if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) ++ glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); ++ else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) ++ glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); ++ else ++ glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); ++ ++ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); ++ AutomaticMipmapUpdate=true; ++ } ++ ++ // enable bilinear filter without mipmaps ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); ++ } + +- u32 compressedImageSize = IImage::getCompressedImageSize(ColorFormat, image->getDimension().Width, image->getDimension().Height); ++ // now get image data and upload to GPU + +- void* source = image->lock(); ++ u32 compressedImageSize = IImage::getCompressedImageSize(ColorFormat, image->getDimension().Width, image->getDimension().Height); + +- IImage* tmpImage = 0; ++ void* source = image->lock(); + +- if (convert) +- { +- tmpImage = new CImage(image->getColorFormat(), image->getDimension()); +- void* dest = tmpImage->lock(); +- convert(source, image->getDimension().getArea(), dest); +- image->unlock(); +- source = dest; +- } ++ IImage* tmpImage = 0; + +- if (newTexture) +- { +- if (IsCompressed) ++ if (convert) + { +- glCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width, +- image->getDimension().Height, 0, compressedImageSize, source); ++ tmpImage = new CImage(image->getColorFormat(), image->getDimension()); ++ void* dest = tmpImage->lock(); ++ convert(source, image->getDimension().getArea(), dest); ++ image->unlock(); ++ source = dest; + } +- else +- glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, +- image->getDimension().Height, 0, PixelFormat, PixelType, source); +- } +- else +- { +- if (IsCompressed) ++ ++ if (newTexture) + { +- glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, +- image->getDimension().Height, PixelFormat, compressedImageSize, source); ++ if (IsCompressed) ++ { ++ glCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width, ++ image->getDimension().Height, 0, compressedImageSize, source); ++ } ++ else ++ glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, ++ image->getDimension().Height, 0, PixelFormat, PixelType, source); + } + else +- glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, +- image->getDimension().Height, PixelFormat, PixelType, source); +- } +- +- if (convert) +- { +- tmpImage->unlock(); +- tmpImage->drop(); +- } +- else +- image->unlock(); +- +- if (!level && newTexture) +- { +- if (IsCompressed && !mipmapData) + { +- if (image->hasMipMaps()) +- mipmapData = static_cast(image->lock())+compressedImageSize; ++ if (IsCompressed) ++ { ++ glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, ++ image->getDimension().Height, PixelFormat, compressedImageSize, source); ++ } + else +- HasMipMaps = false; ++ glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, ++ image->getDimension().Height, PixelFormat, PixelType, source); + } + +- regenerateMipMapLevels(mipmapData); +- +- if (HasMipMaps) // might have changed in regenerateMipMapLevels ++ if (convert) + { +- // enable bilinear mipmap filter +- GLint filteringMipMaps = GL_LINEAR_MIPMAP_NEAREST; +- +- if (filtering != GL_LINEAR) +- filteringMipMaps = GL_NEAREST_MIPMAP_NEAREST; ++ tmpImage->unlock(); ++ tmpImage->drop(); ++ } ++ else ++ image->unlock(); ++ ++ if (glGetError() != GL_NO_ERROR) { ++ static bool warned = false; ++ if ((!retry) && (ColorFormat == ECF_A8R8G8B8)) { ++ ++ if (!warned) { ++ os::Printer::log("Your driver claims to support GL_BGRA but fails on trying to upload a texture, converting to GL_RGBA and trying again", ELL_ERROR); ++ warned = true; ++ } ++ } ++ else if (retry) { ++ os::Printer::log("Neither uploading texture as GL_BGRA nor, converted one using GL_RGBA succeeded", ELL_ERROR); ++ } ++ retry = !retry; ++ continue; ++ } else { ++ retry = false; ++ } + +- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filteringMipMaps); +- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); ++ if (!level && newTexture) ++ { ++ if (IsCompressed && !mipmapData) ++ { ++ if (image->hasMipMaps()) ++ mipmapData = static_cast(image->lock())+compressedImageSize; ++ else ++ HasMipMaps = false; ++ } ++ ++ regenerateMipMapLevels(mipmapData); ++ ++ if (HasMipMaps) // might have changed in regenerateMipMapLevels ++ { ++ // enable bilinear mipmap filter ++ GLint filteringMipMaps = GL_LINEAR_MIPMAP_NEAREST; ++ ++ if (filtering != GL_LINEAR) ++ filteringMipMaps = GL_NEAREST_MIPMAP_NEAREST; ++ ++ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filteringMipMaps); ++ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); ++ } + } +- } + +- if (Driver->testGLError()) +- os::Printer::log("Could not glTexImage2D", ELL_ERROR); ++ if (Driver->testGLError()) ++ os::Printer::log("Could not glTexImage2D", ELL_ERROR); ++ } ++ while(retry); + } + + +--- irrlicht/source/Irrlicht/COGLESTexture.cpp.orig 2014-06-25 00:28:50.820501856 +0200 ++++ irrlicht/source/Irrlicht/COGLESTexture.cpp 2014-06-25 00:08:37.712544692 +0200 +@@ -422,6 +422,9 @@ + source = dest; + } + ++ //clear old error ++ glGetError(); ++ + if (newTexture) + { + if (IsCompressed) diff --git a/build/android/irrlicht-touchcount.patch b/build/android/irrlicht-touchcount.patch new file mode 100644 index 000000000..d4e4b9c3e --- /dev/null +++ b/build/android/irrlicht-touchcount.patch @@ -0,0 +1,30 @@ +--- irrlicht.orig/include/IEventReceiver.h 2014-06-03 19:43:50.433713133 +0200 ++++ irrlicht/include/IEventReceiver.h 2014-06-03 19:44:36.993711489 +0200 +@@ -375,6 +375,9 @@ + // Y position of simple touch. + s32 Y; + ++ // number of current touches ++ s32 touchedCount; ++ + //! Type of touch event. + ETOUCH_INPUT_EVENT Event; + }; +--- irrlicht.orig/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 19:43:50.505713130 +0200 ++++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 19:45:37.265709359 +0200 +@@ -315,6 +315,7 @@ + event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i); + event.TouchInput.X = AMotionEvent_getX(androidEvent, i); + event.TouchInput.Y = AMotionEvent_getY(androidEvent, i); ++ event.TouchInput.touchedCount = AMotionEvent_getPointerCount(androidEvent); + + device->postEventFromUser(event); + } +@@ -326,6 +327,7 @@ + event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, pointerIndex); + event.TouchInput.X = AMotionEvent_getX(androidEvent, pointerIndex); + event.TouchInput.Y = AMotionEvent_getY(androidEvent, pointerIndex); ++ event.TouchInput.touchedCount = AMotionEvent_getPointerCount(androidEvent); + + device->postEventFromUser(event); + } diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk new file mode 100644 index 000000000..3559c2b6d --- /dev/null +++ b/build/android/jni/Android.mk @@ -0,0 +1,310 @@ +LOCAL_PATH := $(call my-dir)/.. + +#LOCAL_ADDRESS_SANITIZER:=true + +include $(CLEAR_VARS) +LOCAL_MODULE := Irrlicht +LOCAL_SRC_FILES := deps/irrlicht/lib/Android/libIrrlicht.a +include $(PREBUILT_STATIC_LIBRARY) + +#include $(CLEAR_VARS) +#LOCAL_MODULE := LevelDB +#LOCAL_SRC_FILES := deps/leveldb/libleveldb.a +#include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := curl +LOCAL_SRC_FILES := deps/curl-7.35.0/lib/.libs/libcurl.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := freetype +LOCAL_SRC_FILES := deps/freetype2-android/Android/obj/local/$(TARGET_ARCH_ABI)/libfreetype2-static.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := openal +LOCAL_SRC_FILES := deps/openal-soft/libs/$(TARGET_LIBDIR)/libopenal.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := ogg +LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libogg.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := vorbis +LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libvorbis.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := ssl +LOCAL_SRC_FILES := deps/openssl-android/libs/$(TARGET_LIBDIR)/libssl.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := crypto +LOCAL_SRC_FILES := deps/openssl-android/libs/$(TARGET_LIBDIR)/libcrypto.so +include $(PREBUILT_SHARED_LIBRARY) + + +include $(CLEAR_VARS) +LOCAL_MODULE := minetest + +LOCAL_CPP_FEATURES += exceptions + +ifdef GPROF +GPROF_DEF=-DGPROF +endif + +LOCAL_CFLAGS := -D_IRR_ANDROID_PLATFORM_ \ + -DHAVE_TOUCHSCREENGUI \ + -DUSE_CURL=1 \ + -DUSE_SOUND=1 \ + -DUSE_FREETYPE=1 \ + $(GPROF_DEF) \ + -pipe -fstrict-aliasing + +ifndef NDEBUG +LOCAL_CFLAGS += -g -D_DEBUG -O0 -fno-omit-frame-pointer +else +LOCAL_CFLAGS += -fexpensive-optimizations -O3 +endif + +ifdef GPROF +PROFILER_LIBS := android-ndk-profiler +LOCAL_CFLAGS += -pg +endif + +# LOCAL_CFLAGS += -fsanitize=address +# LOCAL_LDFLAGS += -fsanitize=address + +ifeq ($(TARGET_ARCH_ABI),x86) +LOCAL_CFLAGS += -fno-stack-protector +endif + +LOCAL_C_INCLUDES := \ + jni/src jni/src/sqlite \ + jni/src/script \ + jni/src/lua/src \ + jni/src/json \ + jni/src/cguittfont \ + deps/irrlicht/include \ + deps/freetype2-android/include \ + deps/curl-7.35.0/include \ + deps/openal-soft/jni/OpenAL/include \ + deps/libvorbis-libogg-android/jni/include + +# deps/leveldb/include \ + +LOCAL_SRC_FILES := \ + jni/src/ban.cpp \ + jni/src/base64.cpp \ + jni/src/biome.cpp \ + jni/src/camera.cpp \ + jni/src/cavegen.cpp \ + jni/src/chat.cpp \ + jni/src/client.cpp \ + jni/src/clientiface.cpp \ + jni/src/clientmap.cpp \ + jni/src/clientmedia.cpp \ + jni/src/clientobject.cpp \ + jni/src/clouds.cpp \ + jni/src/collision.cpp \ + jni/src/connection.cpp \ + jni/src/content_abm.cpp \ + jni/src/content_cao.cpp \ + jni/src/content_cso.cpp \ + jni/src/content_mapblock.cpp \ + jni/src/content_mapnode.cpp \ + jni/src/content_nodemeta.cpp \ + jni/src/content_sao.cpp \ + jni/src/convert_json.cpp \ + jni/src/craftdef.cpp \ + jni/src/database-dummy.cpp \ + jni/src/database-sqlite3.cpp \ + jni/src/database.cpp \ + jni/src/debug.cpp \ + jni/src/defaultsettings.cpp \ + jni/src/drawscene.cpp \ + jni/src/dungeongen.cpp \ + jni/src/emerge.cpp \ + jni/src/environment.cpp \ + jni/src/filecache.cpp \ + jni/src/filesys.cpp \ + jni/src/game.cpp \ + jni/src/genericobject.cpp \ + jni/src/gettext.cpp \ + jni/src/guiChatConsole.cpp \ + jni/src/guiEngine.cpp \ + jni/src/guiFileSelectMenu.cpp \ + jni/src/guiFormSpecMenu.cpp \ + jni/src/guiKeyChangeMenu.cpp \ + jni/src/guiPasswordChange.cpp \ + jni/src/guiTable.cpp \ + jni/src/guiVolumeChange.cpp \ + jni/src/httpfetch.cpp \ + jni/src/hud.cpp \ + jni/src/inventory.cpp \ + jni/src/inventorymanager.cpp \ + jni/src/itemdef.cpp \ + jni/src/keycode.cpp \ + jni/src/light.cpp \ + jni/src/localplayer.cpp \ + jni/src/log.cpp \ + jni/src/main.cpp \ + jni/src/map.cpp \ + jni/src/mapblock.cpp \ + jni/src/mapblock_mesh.cpp \ + jni/src/mapgen.cpp \ + jni/src/mapgen_indev.cpp \ + jni/src/mapgen_math.cpp \ + jni/src/mapgen_singlenode.cpp \ + jni/src/mapgen_v6.cpp \ + jni/src/mapgen_v7.cpp \ + jni/src/mapnode.cpp \ + jni/src/mapsector.cpp \ + jni/src/mesh.cpp \ + jni/src/mods.cpp \ + jni/src/nameidmapping.cpp \ + jni/src/nodedef.cpp \ + jni/src/nodemetadata.cpp \ + jni/src/nodetimer.cpp \ + jni/src/noise.cpp \ + jni/src/object_properties.cpp \ + jni/src/particles.cpp \ + jni/src/pathfinder.cpp \ + jni/src/player.cpp \ + jni/src/porting_android.cpp \ + jni/src/porting.cpp \ + jni/src/quicktune.cpp \ + jni/src/rollback.cpp \ + jni/src/rollback_interface.cpp \ + jni/src/serialization.cpp \ + jni/src/server.cpp \ + jni/src/serverlist.cpp \ + jni/src/serverobject.cpp \ + jni/src/sha1.cpp \ + jni/src/shader.cpp \ + jni/src/sky.cpp \ + jni/src/socket.cpp \ + jni/src/sound.cpp \ + jni/src/sound_openal.cpp \ + jni/src/staticobject.cpp \ + jni/src/subgame.cpp \ + jni/src/test.cpp \ + jni/src/tile.cpp \ + jni/src/tool.cpp \ + jni/src/treegen.cpp \ + jni/src/version.cpp \ + jni/src/voxel.cpp \ + jni/src/voxelalgorithms.cpp \ + jni/src/util/directiontables.cpp \ + jni/src/util/numeric.cpp \ + jni/src/util/pointedthing.cpp \ + jni/src/util/serialize.cpp \ + jni/src/util/string.cpp \ + jni/src/util/timetaker.cpp \ + jni/src/touchscreengui.cpp + +# jni/src/database-leveldb.cpp \ + +# lua api +LOCAL_SRC_FILES += \ + jni/src/script/common/c_content.cpp \ + jni/src/script/common/c_converter.cpp \ + jni/src/script/common/c_internal.cpp \ + jni/src/script/common/c_types.cpp \ + jni/src/script/cpp_api/s_base.cpp \ + jni/src/script/cpp_api/s_entity.cpp \ + jni/src/script/cpp_api/s_env.cpp \ + jni/src/script/cpp_api/s_inventory.cpp \ + jni/src/script/cpp_api/s_item.cpp \ + jni/src/script/cpp_api/s_mainmenu.cpp \ + jni/src/script/cpp_api/s_node.cpp \ + jni/src/script/cpp_api/s_nodemeta.cpp \ + jni/src/script/cpp_api/s_player.cpp \ + jni/src/script/cpp_api/s_server.cpp \ + jni/src/script/cpp_api/s_async.cpp \ + jni/src/script/lua_api/l_base.cpp \ + jni/src/script/lua_api/l_craft.cpp \ + jni/src/script/lua_api/l_env.cpp \ + jni/src/script/lua_api/l_inventory.cpp \ + jni/src/script/lua_api/l_item.cpp \ + jni/src/script/lua_api/l_mainmenu.cpp \ + jni/src/script/lua_api/l_mapgen.cpp \ + jni/src/script/lua_api/l_nodemeta.cpp \ + jni/src/script/lua_api/l_nodetimer.cpp \ + jni/src/script/lua_api/l_noise.cpp \ + jni/src/script/lua_api/l_object.cpp \ + jni/src/script/lua_api/l_particles.cpp \ + jni/src/script/lua_api/l_rollback.cpp \ + jni/src/script/lua_api/l_server.cpp \ + jni/src/script/lua_api/l_settings.cpp \ + jni/src/script/lua_api/l_util.cpp \ + jni/src/script/lua_api/l_vmanip.cpp \ + jni/src/script/scripting_game.cpp \ + jni/src/script/scripting_mainmenu.cpp + +#freetype2 support +LOCAL_SRC_FILES += \ + jni/src/cguittfont/xCGUITTFont.cpp + +# lua +LOCAL_SRC_FILES += \ + jni/src/lua/src/lapi.c \ + jni/src/lua/src/lauxlib.c \ + jni/src/lua/src/lbaselib.c \ + jni/src/lua/src/lcode.c \ + jni/src/lua/src/ldblib.c \ + jni/src/lua/src/ldebug.c \ + jni/src/lua/src/ldo.c \ + jni/src/lua/src/ldump.c \ + jni/src/lua/src/lfunc.c \ + jni/src/lua/src/lgc.c \ + jni/src/lua/src/linit.c \ + jni/src/lua/src/liolib.c \ + jni/src/lua/src/llex.c \ + jni/src/lua/src/lmathlib.c \ + jni/src/lua/src/lmem.c \ + jni/src/lua/src/loadlib.c \ + jni/src/lua/src/lobject.c \ + jni/src/lua/src/lopcodes.c \ + jni/src/lua/src/loslib.c \ + jni/src/lua/src/lparser.c \ + jni/src/lua/src/lstate.c \ + jni/src/lua/src/lstring.c \ + jni/src/lua/src/lstrlib.c \ + jni/src/lua/src/ltable.c \ + jni/src/lua/src/ltablib.c \ + jni/src/lua/src/ltm.c \ + jni/src/lua/src/lundump.c \ + jni/src/lua/src/lvm.c \ + jni/src/lua/src/lzio.c \ + jni/src/lua/src/print.c + +# sqlite +LOCAL_SRC_FILES += jni/src/sqlite/sqlite3.c + +# jthread +LOCAL_SRC_FILES += \ + jni/src/jthread/pthread/jevent.cpp \ + jni/src/jthread/pthread/jmutex.cpp \ + jni/src/jthread/pthread/jsemaphore.cpp \ + jni/src/jthread/pthread/jthread.cpp + +# json +LOCAL_SRC_FILES += jni/src/json/jsoncpp.cpp + +LOCAL_SHARED_LIBRARIES := openal ogg vorbis ssl crypto +LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl android_native_app_glue $(PROFILER_LIBS) +# LevelDB +LOCAL_LDLIBS := -lEGL -llog -lGLESv1_CM -lGLESv2 -lz -landroid + +include $(BUILD_SHARED_LIBRARY) + +# at the end of Android.mk +ifdef GPROF +$(call import-module,android-ndk-profiler) +endif +$(call import-module,android/native_app_glue) diff --git a/build/android/jni/Application.mk b/build/android/jni/Application.mk new file mode 100644 index 000000000..b7ffc56a1 --- /dev/null +++ b/build/android/jni/Application.mk @@ -0,0 +1,8 @@ +# NDK_TOOLCHAIN_VERSION := clang3.3 + +APP_PLATFORM := android-9 +APP_MODULES := minetest +APP_STL := gnustl_static + +APP_CPPFLAGS += -fexceptions +APP_GNUSTL_FORCE_CPP_FEATURES := rtti diff --git a/build/android/libvorbis-libogg-fpu.patch b/build/android/libvorbis-libogg-fpu.patch new file mode 100644 index 000000000..52ab397ac --- /dev/null +++ b/build/android/libvorbis-libogg-fpu.patch @@ -0,0 +1,37 @@ +--- libvorbis-libogg-android/jni/libvorbis-jni/Android.mk.orig 2014-06-17 19:22:50.621559073 +0200 ++++ libvorbis-libogg-android/jni/libvorbis-jni/Android.mk 2014-06-17 19:38:20.641581140 +0200 +@@ -4,9 +4,6 @@ + + LOCAL_MODULE := vorbis-jni + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -fsigned-char +-ifeq ($(TARGET_ARCH),arm) +- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp +-endif + + LOCAL_SHARED_LIBRARIES := libogg libvorbis + +--- libvorbis-libogg-android/jni/libvorbis/Android.mk.orig 2014-06-17 19:22:39.077558797 +0200 ++++ libvorbis-libogg-android/jni/libvorbis/Android.mk 2014-06-17 19:38:52.121581887 +0200 +@@ -4,9 +4,6 @@ + + LOCAL_MODULE := libvorbis + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -ffast-math -fsigned-char +-ifeq ($(TARGET_ARCH),arm) +- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp +-endif + LOCAL_SHARED_LIBRARIES := libogg + + LOCAL_SRC_FILES := \ +--- libvorbis-libogg-android/jni/libogg/Android.mk.orig 2014-06-17 19:22:33.965558675 +0200 ++++ libvorbis-libogg-android/jni/libogg/Android.mk 2014-06-17 19:38:25.337581252 +0200 +@@ -4,10 +4,6 @@ + + LOCAL_MODULE := libogg + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -ffast-math -fsigned-char +-ifeq ($(TARGET_ARCH),arm) +- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp +-endif +- + + LOCAL_SRC_FILES := \ + bitwise.c \ diff --git a/build/android/project.properties b/build/android/project.properties new file mode 100644 index 000000000..cc2a7c5cf --- /dev/null +++ b/build/android/project.properties @@ -0,0 +1 @@ +target=android-10 diff --git a/build/android/res/drawable-hdpi/irr_icon.png b/build/android/res/drawable-hdpi/irr_icon.png new file mode 100644 index 000000000..0b6861a0d Binary files /dev/null and b/build/android/res/drawable-hdpi/irr_icon.png differ diff --git a/build/android/res/drawable-ldpi/irr_icon.png b/build/android/res/drawable-ldpi/irr_icon.png new file mode 100644 index 000000000..b8c5d0177 Binary files /dev/null and b/build/android/res/drawable-ldpi/irr_icon.png differ diff --git a/build/android/res/drawable-mdpi/irr_icon.png b/build/android/res/drawable-mdpi/irr_icon.png new file mode 100644 index 000000000..951a7f8c1 Binary files /dev/null and b/build/android/res/drawable-mdpi/irr_icon.png differ diff --git a/build/android/res/drawable-xhdpi/irr_icon.png b/build/android/res/drawable-xhdpi/irr_icon.png new file mode 100644 index 000000000..2ec528ef7 Binary files /dev/null and b/build/android/res/drawable-xhdpi/irr_icon.png differ diff --git a/build/android/res/layout/assetcopy.xml b/build/android/res/layout/assetcopy.xml new file mode 100644 index 000000000..ade4b0c98 --- /dev/null +++ b/build/android/res/layout/assetcopy.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/build/android/res/values/styles.xml b/build/android/res/values/styles.xml new file mode 100644 index 000000000..25b8df5a3 --- /dev/null +++ b/build/android/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/build/android/src/org/minetest/minetest/MinetestAssetCopy.java b/build/android/src/org/minetest/minetest/MinetestAssetCopy.java new file mode 100644 index 000000000..652a00831 --- /dev/null +++ b/build/android/src/org/minetest/minetest/MinetestAssetCopy.java @@ -0,0 +1,288 @@ +package org.minetest.minetest; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.Vector; + +import android.app.Activity; +import android.content.res.AssetFileDescriptor; + +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; +import android.view.Display; +import android.widget.ProgressBar; +import android.widget.TextView; + +public class MinetestAssetCopy extends Activity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.assetcopy); + + m_ProgressBar = (ProgressBar) findViewById(R.id.progressBar1); + m_Filename = (TextView) findViewById(R.id.textView1); + + Display display = getWindowManager().getDefaultDisplay(); + m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8); + m_ProgressBar.invalidate(); + + m_AssetCopy = new copyAssetTask(); + m_AssetCopy.execute(); + } + + ProgressBar m_ProgressBar; + TextView m_Filename; + + copyAssetTask m_AssetCopy; + + private class copyAssetTask extends AsyncTask{ + + private void copyElement(String name, String path) { + String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath(); + String full_path; + if (path != "") { + full_path = path + "/" + name; + } + else { + full_path = name; + } + //is a folder read asset list + if (m_foldernames.contains(full_path)) { + m_Foldername = full_path; + publishProgress(0); + File current_folder = new File(baseDir + "/" + full_path); + if (!current_folder.exists()) { + if (!current_folder.mkdirs()) { + Log.w("MinetestAssetCopy","\t failed create folder: " + baseDir + "/" + full_path); + } + else { + Log.w("MinetestAssetCopy","\t created folder: " + baseDir + "/" + full_path); + } + } + try { + String[] current_assets = getAssets().list(full_path); + for(int i=0; i < current_assets.length; i++) { + copyElement(current_assets[i],full_path); + } + } catch (IOException e) { + Log.w("MinetestAssetCopy","\t failed to read contents of folder"); + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + //is a file just copy + else { + boolean refresh = true; + + File testme = new File(baseDir + "/" + full_path); + + long asset_filesize = -1; + long stored_filesize = -1; + + if (testme.exists()) { + try { + AssetFileDescriptor fd = getAssets().openFd(full_path); + asset_filesize = fd.getLength(); + fd.close(); + } catch (IOException e) { + refresh = true; + m_asset_size_unknown.add(full_path); + } + + stored_filesize = testme.length(); + + if (asset_filesize == stored_filesize) { + refresh = false; + } + + } + + if (refresh) { + m_tocopy.add(full_path); + } + } + } + + private long getFullSize(String filename) { + long size = 0; + try { + InputStream src = getAssets().open(filename); + byte[] buf = new byte[1024]; + + int len = 0; + while ((len = src.read(buf)) > 0) { + size += len; + } + } + catch (IOException e) { + e.printStackTrace(); + } + return size; + } + + @Override + protected String doInBackground(String... files) { + + m_foldernames = new Vector(); + m_tocopy = new Vector(); + m_asset_size_unknown = new Vector(); + String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/"; + + File TempFolder = new File(baseDir + "Minetest/tmp/"); + + if (!TempFolder.exists()) { + TempFolder.mkdir(); + } + else { + File[] todel = TempFolder.listFiles(); + + for(int i=0; i < todel.length; i++) { + Log.w("MinetestAssetCopy","deleting: " + todel[i].getAbsolutePath()); + todel[i].delete(); + } + } + + // add a .nomedia file + try { + OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia"); + dst.close(); + } catch (IOException e) { + Log.w("MinetestAssetCopy","Failed to create .nomedia file"); + e.printStackTrace(); + } + + try { + InputStream is = getAssets().open("index.txt"); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + + String line = reader.readLine(); + while(line != null){ + m_foldernames.add(line); + line = reader.readLine(); + } + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + copyElement("Minetest",""); + + m_copy_started = true; + m_ProgressBar.setMax(m_tocopy.size()); + + for (int i = 0; i < m_tocopy.size(); i++) { + try { + String filename = m_tocopy.get(i); + publishProgress(i); + + boolean asset_size_unknown = false; + long filesize = -1; + + if (m_asset_size_unknown.contains(filename)) { + File testme = new File(baseDir + "/" + filename); + + if(testme.exists()) { + filesize = testme.length(); + } + asset_size_unknown = true; + } + + InputStream src; + try { + src = getAssets().open(filename); + } catch (IOException e) { + Log.w("MinetestAssetCopy","Copying file: " + filename + " FAILED (not in assets)"); + // TODO Auto-generated catch block + e.printStackTrace(); + continue; + } + + // Transfer bytes from in to out + byte[] buf = new byte[1*1024]; + int len = src.read(buf, 0, 1024); + + /* following handling is crazy but we need to deal with */ + /* compressed assets.Flash chips limited livetime sue to */ + /* write operations, we can't allow large files to destroy */ + /* users flash. */ + if (asset_size_unknown) { + if ( (len > 0) && (len < buf.length) && (len == filesize)) { + src.close(); + continue; + } + + if (len == buf.length) { + src.close(); + long size = getFullSize(filename); + if ( size == filesize) { + continue; + } + src = getAssets().open(filename); + len = src.read(buf, 0, 1024); + } + } + if (len > 0) { + int total_filesize = 0; + OutputStream dst; + try { + dst = new FileOutputStream(baseDir + "/" + filename); + } catch (IOException e) { + Log.w("MinetestAssetCopy","Copying file: " + baseDir + + "/" + filename + " FAILED (couldn't open output file)"); + e.printStackTrace(); + src.close(); + continue; + } + dst.write(buf, 0, len); + total_filesize += len; + + while ((len = src.read(buf)) > 0) { + dst.write(buf, 0, len); + total_filesize += len; + } + + dst.close(); + Log.w("MinetestAssetCopy","Copied file: " + m_tocopy.get(i) + " (" + total_filesize + " bytes)"); + } + else if (len < 0) { + Log.w("MinetestAssetCopy","Copying file: " + m_tocopy.get(i) + " failed, size < 0"); + } + src.close(); + } catch (IOException e) { + Log.w("MinetestAssetCopy","Copying file: " + m_tocopy.get(i) + " failed"); + e.printStackTrace(); + } + } + + return ""; + } + + protected void onProgressUpdate(Integer... progress) { + if (m_copy_started) { + m_ProgressBar.setProgress(progress[0]); + m_Filename.setText(m_tocopy.get(progress[0])); + } + else { + m_Filename.setText("scanning " + m_Foldername + " ..."); + } + } + + protected void onPostExecute (String result) { + finish(); + } + boolean m_copy_started = false; + String m_Foldername = "media"; + Vector m_foldernames; + Vector m_tocopy; + Vector m_asset_size_unknown; + } +} diff --git a/build/android/src/org/minetest/minetest/MinetestTextEntry.java b/build/android/src/org/minetest/minetest/MinetestTextEntry.java new file mode 100644 index 000000000..db175a483 --- /dev/null +++ b/build/android/src/org/minetest/minetest/MinetestTextEntry.java @@ -0,0 +1,91 @@ +package org.minetest.minetest; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.text.InputType; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnKeyListener; +import android.widget.EditText; + +public class MinetestTextEntry extends Activity { + public AlertDialog mTextInputDialog; + public EditText mTextInputWidget; + + private final int MultiLineTextInput = 1; + private final int SingleLineTextInput = 2; + private final int SingleLinePasswordInput = 3; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Bundle b = getIntent().getExtras(); + String acceptButton = b.getString("EnterButton"); + String hint = b.getString("hint"); + String current = b.getString("current"); + int editType = b.getInt("editType"); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + mTextInputWidget = new EditText(this); + mTextInputWidget.setHint(hint); + mTextInputWidget.setText(current); + mTextInputWidget.setMinWidth(300); + if (editType == SingleLinePasswordInput) { + mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + } + else { + mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT); + } + + + builder.setView(mTextInputWidget); + + if (editType == MultiLineTextInput) { + builder.setPositiveButton(acceptButton, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) + { pushResult(mTextInputWidget.getText().toString()); } + }); + } + + builder.setOnCancelListener(new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + cancelDialog(); + } + }); + + mTextInputWidget.setOnKeyListener(new OnKeyListener() { + @Override + public boolean onKey(View view, int KeyCode, KeyEvent event) { + if ( KeyCode == KeyEvent.KEYCODE_ENTER){ + + pushResult(mTextInputWidget.getText().toString()); + return true; + } + return false; + } + }); + + mTextInputDialog = builder.create(); + mTextInputDialog.show(); + } + + public void pushResult(String text) { + Intent resultData = new Intent(); + resultData.putExtra("text", text); + setResult(Activity.RESULT_OK,resultData); + mTextInputDialog.dismiss(); + finish(); + } + + public void cancelDialog() { + setResult(Activity.RESULT_CANCELED); + mTextInputDialog.dismiss(); + finish(); + } +} diff --git a/build/android/src/org/minetest/minetest/MtNativeActivity.java b/build/android/src/org/minetest/minetest/MtNativeActivity.java new file mode 100644 index 000000000..ba7d62169 --- /dev/null +++ b/build/android/src/org/minetest/minetest/MtNativeActivity.java @@ -0,0 +1,93 @@ +package org.minetest.minetest; + +import android.app.NativeActivity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.WindowManager; + +public class MtNativeActivity extends NativeActivity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + m_MessagReturnCode = -1; + m_MessageReturnValue = ""; + + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + + public void copyAssets() { + Intent intent = new Intent(this, MinetestAssetCopy.class); + startActivity(intent); + } + + public void showDialog(String acceptButton, String hint, String current, + int editType) { + + Intent intent = new Intent(this, MinetestTextEntry.class); + Bundle params = new Bundle(); + params.putString("acceptButton", acceptButton); + params.putString("hint", hint); + params.putString("current", current); + params.putInt("editType", editType); + intent.putExtras(params); + startActivityForResult(intent, 101); + m_MessageReturnValue = ""; + m_MessagReturnCode = -1; + } + + public static native void putMessageBoxResult(String text); + + /* ugly code to workaround putMessageBoxResult not beeing found */ + public int getDialogState() { + return m_MessagReturnCode; + } + + public String getDialogValue() { + m_MessagReturnCode = -1; + return m_MessageReturnValue; + } + + public float getDensity() { + return getResources().getDisplayMetrics().density; + } + + public int getDisplayWidth() { + return getResources().getDisplayMetrics().widthPixels; + } + + public int getDisplayHeight() { + return getResources().getDisplayMetrics().heightPixels; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + if (requestCode == 101) { + if (resultCode == RESULT_OK) { + String text = data.getStringExtra("text"); + m_MessagReturnCode = 0; + m_MessageReturnValue = text; + } + else { + m_MessagReturnCode = 1; + } + } + } + + static { + System.loadLibrary("openal"); + System.loadLibrary("ogg"); + System.loadLibrary("vorbis"); + System.loadLibrary("ssl"); + System.loadLibrary("crypto"); + } + + private int m_MessagReturnCode; + private String m_MessageReturnValue; +} -- cgit v1.2.3