]> localhost Git - gists.git/commitdiff
Add Android NDK barebones app
authormisomosi <[email protected]>
Sun, 21 Jun 2026 22:08:45 +0000 (18:08 -0400)
committermisomosi <[email protected]>
Sun, 21 Jun 2026 22:08:45 +0000 (18:08 -0400)
android-native-app-barebones/.gitignore [new file with mode: 0644]
android-native-app-barebones/AndroidManifest.xml [new file with mode: 0644]
android-native-app-barebones/LICENSE [new file with mode: 0644]
android-native-app-barebones/README.md [new file with mode: 0644]
android-native-app-barebones/build.bat [new file with mode: 0644]
android-native-app-barebones/build.sh [new file with mode: 0644]
android-native-app-barebones/main.c [new file with mode: 0644]

diff --git a/android-native-app-barebones/.gitignore b/android-native-app-barebones/.gitignore
new file mode 100644 (file)
index 0000000..6a4d5ee
--- /dev/null
@@ -0,0 +1,35 @@
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# Build directory
+build/
diff --git a/android-native-app-barebones/AndroidManifest.xml b/android-native-app-barebones/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..34b3ab9
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="org.tf2spi.barebones"
+        android:versionCode="35" android:versionName="1.0" >
+    <uses-sdk android:minSdkVersion="29" />
+    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+    <application android:allowBackup="false" android:label="barebones" android:hasCode="false" >
+        <activity android:name="android.app.NativeActivity"
+            android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+            android:configChanges="orientation|keyboardHidden|screenSize"
+            android:screenOrientation="landscape" android:launchMode="singleTask"
+            android:clearTaskOnLaunch="true" android:exported="true">
+            <meta-data android:name="android.app.lib_name" android:value="barebones" />
+            <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-native-app-barebones/LICENSE b/android-native-app-barebones/LICENSE
new file mode 100644 (file)
index 0000000..fdddb29
--- /dev/null
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <https://unlicense.org>
diff --git a/android-native-app-barebones/README.md b/android-native-app-barebones/README.md
new file mode 100644 (file)
index 0000000..f28a283
--- /dev/null
@@ -0,0 +1,37 @@
+# android-native-app-barebones
+The most elementary, stripped-down template of building an APK using Android tools
+
+## Required Environment Variables
+
+* __ANDROID_HOME__: Path where your [Android command line tools](https://developer.android.com/studio#command-line-tools-only) are installed
+* __JAVA_HOME__:    Path where your JDK is installed
+* __PATH__:         The ``bin`` folder from __JAVA_HOME__ must be included
+
+## Required SDKManager Installations
+
+The scripts work for the following package versions which can be installed via ``sdkmanager``
+
+```sh
+sdkmanager 'build-tools;36.0.0' 'ndk;29.0.13113456' 'platforms;android-35'
+```
+
+In addition, you should also install ``platform-tools`` via ``sdkmanager`` to use ``adb``
+
+## Instructions
+
+You can simply invoke ``build.sh`` or ``build.bat`` for ``/bin/sh``
+or ``CMD.EXE`` respectfully and it should build ``build/app-signed.apk``
+
+To keep the scripts simple and easy to read, the APK only is built for
+AARCH64so you need a 64-bit ARM Android device handy or to emulate
+such a device (caveat: this is slow to do on X86\_64).
+
+After this, set up an ADB daemon and install ``app-signed.apk`` using ``adb``
+and run it on your device. It should just be a black screen that doesn't crash.
+
+Additionally, you can look at logs via ``adb logcat "*:S barebones"``
+and you should find a nice little "hello" from the app you built.
+
+If, for whatever reason, it's erroring out, try to look at
+``adb logcat *:E``. This will usually output a java exception
+from your app which lets you know why your app failed to load.
diff --git a/android-native-app-barebones/build.bat b/android-native-app-barebones/build.bat
new file mode 100644 (file)
index 0000000..651781a
--- /dev/null
@@ -0,0 +1,36 @@
+@echo off
+
+REM For simplicity, version are hardcoded for build tools, NDK, and SDK.
+REM In addition, the architecture is hardcoded to AARCH64.
+REM Feel free to change these to your liking!
+REM Make sure to also edit AndroidManifest.xml if you change SDK versions
+SET BUILD=build
+SET JNI=lib\arm64-v8a
+SET BUILD_TOOLS=%ANDROID_HOME%\build-tools\36.0.0
+SET ANDROID_NDK=%ANDROID_HOME%\ndk\29.0.13113456
+SET ANDROID_TOOLCHAIN=%ANDROID_NDK%\toolchains\llvm\prebuilt\windows-x86_64
+SET CC=%ANDROID_TOOLCHAIN%\bin\clang --target=aarch64-linux-android35
+SET ANDROID_JAR=%ANDROID_HOME%\platforms\android-35\android.jar
+SET SYSROOT=%ANDROID_TOOLCHAIN%\sysroot
+SET NATIVE_APP_GLUE_DIR=%ANDROID_NDK%\sources\android\native_app_glue
+SET PLATFORM_TOOLS=%ANDROID_HOME%\platform-tools
+
+REM For simplicity, project hardcoded to "barebones"
+REM Make sure to also edit AndroidManifest.xml if you change this
+SET LIB=libbarebones.so
+SET CFLAGS=-lm -lc -llog -landroid -ldl -g -Og -shared -fPIC --sysroot=%SYSROOT%
+SET KEYSTORE=%BUILD%\barebones.keystore
+SET KEYPASS=barebones
+
+@echo on
+
+MKDIR %BUILD%\%JNI% 2>NUL
+if not exist %KEYSTORE% (%JAVA_HOME%\bin\keytool -genkeypair -validity 10000 -dname "CN=barebones,O=Android,C=ES" -keystore %KEYSTORE% -storepass %KEYPASS% -keypass %KEYPASS% -alias barebones -keyalg RSA)
+%CC% -I %NATIVE_APP_GLUE_DIR% %NATIVE_APP_GLUE_DIR%\android_native_app_glue.c main.c -o %BUILD%\%JNI%\%LIB% %CFLAGS%
+
+%BUILD_TOOLS%\aapt package -f -M AndroidManifest.xml -I %ANDROID_JAR% -F %BUILD%\app.apk
+PUSHD %BUILD%
+%BUILD_TOOLS%\aapt add app.apk %JNI:\=/%/%LIB%
+POPD
+%BUILD_TOOLS%\zipalign -f 4 %BUILD%\app.apk %BUILD%\app-signed.apk
+%BUILD_TOOLS%\apksigner sign --ks %KEYSTORE% --ks-pass pass:%KEYPASS% %BUILD%\app-signed.apk
diff --git a/android-native-app-barebones/build.sh b/android-native-app-barebones/build.sh
new file mode 100644 (file)
index 0000000..e68bcf2
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/sh
+# For simplicity, version are hardcoded for build tools, NDK, and SDK.
+# In addition, the architecture is hardcoded to AARCH64.
+# Feel free to change these to your liking!
+# Make sure to also edit AndroidManifest.xml if you change SDK versions
+BUILD=build
+JNI=lib/arm64-v8a
+BUILD_TOOLS=$ANDROID_HOME/build-tools/36.0.0
+ANDROID_NDK=$ANDROID_HOME/ndk/29.0.13113456
+ANDROID_TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt
+if [ -d "$ANDROID_TOOLCHAIN/windows-x86_64" ] ; then
+       # Those who use MSYS (like me) use these variables.
+       # As a bounus, it also works under busybox-w32.
+       ANDROID_TOOLCHAIN=$ANDROID_TOOLCHAIN/windows-x86_64
+       EXT=".bat"
+else
+       ANDROID_TOOLCHAIN=$ANDROID_TOOLCHAIN/linux-x86_64
+       EXT=""
+fi
+CC=$ANDROID_TOOLCHAIN/bin/aarch64-linux-android35-clang
+ANDROID_JAR=$ANDROID_HOME/platforms/android-35/android.jar
+SYSROOT=$ANDROID_TOOLCHAIN/sysroot
+NATIVE_APP_GLUE_DIR=$ANDROID_NDK/sources/android/native_app_glue
+PLATFORM_TOOLS=$ANDROID_HOME/platform-tools
+
+# For simplicity, project hardcoded to "barebones"
+# Make sure to also edit AndroidManifest.xml if you change this
+LIB=libbarebones.so
+CFLAGS="-lm -lc -llog -landroid -ldl -g -Og -shared -fPIC --sysroot=$SYSROOT"
+KEYSTORE=$BUILD/barebones.keystore
+KEYPASS=barebones
+
+set -e
+
+mkdir -p $BUILD/$JNI
+if [ ! -f $KEYSTORE ] ; then
+       ($JAVA_HOME/bin/keytool -genkeypair -validity 10000 -dname "CN=barebones,O=Android,C=ES" -keystore $KEYSTORE -storepass $KEYPASS -keypass $KEYPASS -alias barebones -keyalg RSA)
+fi
+$CC -I $NATIVE_APP_GLUE_DIR $NATIVE_APP_GLUE_DIR/android_native_app_glue.c main.c -o $BUILD/$JNI/$LIB $CFLAGS
+
+# Only APKSigner out of all of these is a batch file on Windows
+$BUILD_TOOLS/aapt package -f -M AndroidManifest.xml -I $ANDROID_JAR -F $BUILD/app.apk
+(cd $BUILD && $BUILD_TOOLS/aapt add app.apk $JNI/$LIB)
+$BUILD_TOOLS/zipalign -f 4 $BUILD/app.apk $BUILD/app-signed.apk
+$BUILD_TOOLS/apksigner"$EXT" sign --ks $KEYSTORE --ks-pass pass:$KEYPASS $BUILD/app-signed.apk
diff --git a/android-native-app-barebones/main.c b/android-native-app-barebones/main.c
new file mode 100644 (file)
index 0000000..4d191d3
--- /dev/null
@@ -0,0 +1,16 @@
+#include <android_native_app_glue.h>
+#include <android/log.h>
+#include <jni.h>
+
+void handle_cmd(struct android_app *app, int32_t cmd) {}
+void android_main(struct android_app *app) {
+       (void)__android_log_print(ANDROID_LOG_INFO, "barebones", "Barebones Android app says hello!");
+       app->onAppCmd = handle_cmd;
+       while (!app->destroyRequested) {
+               struct android_poll_source *source;
+               int events;
+               switch (ALooper_pollOnce(-1, 0, &events, (void **)&source)) {
+                       default: if (source) source->process(app, source);
+               }
+       }
+}