A minimal example of building a C Android NDK app from the command line without writing java code. I also wrote an accompanying article.
I currently use a musl libc based distro (Chimera Linux) and Google does not distribute Android Studio for such a system. Luckily, a good samaritan has gone through the work of compiling the Android SDK tools and Android NDK into static binaries that will work on any Linux system.
The rawdraw project provides a fantastic example of how to build a native Android applicaiton from the command line, but it is still somewhat complicated. After getting my GLFW applications to compile for Android, I distilled the process down to this tiny OpenGL ES 2.0 example.
You'll need an OpenJDK install,
a copy of the Android SDK command line tools (aapt
or aapt2
, zipalign
, apksigner
),
and a copy of the Android NDK toolchains. See my article for several ways
to acquire these.
You will also need a copy of
android.jar
for the target android SDK version. A copy can be pulled from the
Sable collection by running ANDROID_VERSION=XX ./pull_android_jar.sh
.
Finally, you will need a keystore file to sign your application. E.g. using keytool
:
keytool -genkey -v -keystore mykey.keystore -alias mykey -keyalg RSA -keysize 2048 \
-validity 10000 -storepass mypassword -keypass mypassword \
-dname "CN=example.com, OU=ID, O=Example, L=Doe, S=John, C=GB"
You will need to export the following environment variables in order to run ./build.sh
:
# ANDROID_VERSION: the target android version number (must be >=22)
# ANDROID_JAR: a path to the android.jar file (see pull_android_jar.sh)
# ANDROID_AAPT: path to android sdk aapt
# ANDROID_ZIPALIGN: path to android sdk zipalign
# ANDROID_APKSIGNER: path to android sdk apksizinger
# ANDROID_CLANG: path to android ndk clang
# APP_NAME: the name of your app
# ORG_NAME: the name of your organization
# KEYSTORE_FILE: path to keystore file
# STORE_PASS: keystore password
# KEY_PASS: key password
# CFLAGS: common flags to be passed to C compiler
# LDFLAGS: common flags to be passed to the linker
An example build command:
ANDROID_VERSION=30 ./pull_android_jar.sh
ANDROID_VERSION=30 \
ANDROID_JAR=./android-30.jar \
ANDROID_AAPT=/home/user/android_sdk/build-tools/35.0.1/aapt \
ANDROID_ZIPALIGN=/home/user/android_sdk/build-tools/35.0.1/zipalign \
ANDROID_APKSIGNER=/home/user/android_sdk/build-tools/35.0.1/apksigner \
ANDROID_CLANG=/home/user/android_sdk/ndk/29.0.13599879/toolchains/llvm/prebuilt/linux-x86_64/bin/clang \
APP_NAME=seglapp \
ORG_NAME=avensegl \
KEYSTORE_FILE=./mykey.keystore \
STORE_PASS=mypassword \
KEY_PASS=mypassword \
CFLAGS="-Wall -Wextra -Wno-unused-parameter -std=c11 -O3 -g0 -s" \
./build.sh
You will need to enable USB Debugging on the test device (or use an emulator) and then
install the APK with adb
:
adb install ./build_android/seglapp.apk # replace seglapp.apk with your app name
To view debug logs you can run:
adb shell logcat SEGLAPP:I *:S
To uninstall the app you can run:
adb uninstall org.avensegl.seglapp # replace avensegl and seglapp with your org and app names