RawDrawAndroid builds a 25kB APK from a Makefile and one C file
Build android apps without any java, entirely in C and Make
At a glance
- What is it?
- RawDrawAndroid replaces the Android Gradle toolchain with a Makefile, native C sources and android_native_app_glue, targeting small APKs and short build cycles. It suits C programmers who want visible build steps, and it is a poor fit for anyone who needs Play Store tooling or an IDE.
- Who is it for?
- Adopt it if you write C, want an APK you can read end to end, and can accept owning your own manifest, keystore and dependency list by hand. Do not adopt it if your work depends on Play Console publishing tools, AndroidX or Play Services, or if a team expects a conventional Gradle project layout that any hire can open without help.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 48 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- cnlohr/rawdrawandroid4,334 ★ · +17
| Repository | 2026-09-23 | 2026-11-14 |
|---|---|---|
| cnlohr/rawdrawandroid | 4.3k | 4.3k |
17 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The toolchain question rawdrawandroid answers first
Most Android C work starts inside Gradle, and Gradle hides the commands it runs. rawdrawandroid takes the opposite position: the build is a Makefile, so every compiler invocation and linker flag is a line you can read and edit. The project's stated target is a full build, install and launch cycle in about 2 seconds, with an APK of roughly 25kB at API 26. Moving to API 30, so the APK can carry both ARM64 and ARM32, pushes that figure to about 45kB.
That doubling is the closest thing to a benchmark the project offers, and it is worth reading carefully. The size cost is not the framework getting bigger. It is the addition of a second architecture. The same code is doing the same work; the package simply has to answer to more phones.
The audience is narrow and obvious once stated. RawDrawAndroid targets the developer who already lives in C, already thinks in rawdraw, and is annoyed by the dependency weight of the standard Android route. The repository builds on the same rawdraw ideas the author uses on ESP8266 and Raspberry Pi hardware, and the submodules sit in the tree as rawdraw and cnfa.
android_native_app_glue.c does the work Java would otherwise do
The repository has no Java sources. Instead, android_native_app_glue.c and its header sit at the top level and compile into every build through the RAWDRAWANDROIDSRCS variable in the Makefile. That file is the native entry point: it is where the Activity lifecycle is bridged into C.
What the demo in test.c reaches from there covers a specific list. An OpenGL ES window, accelerometer and gyro input with multi-touch, an on-screen Android keyboard for key input, asset files stored inside the APK and read through AAssetManager, permission requests for things like audio, and direct USB device access through android_usb_devices.c. The permissions and USB examples are not written in the main README body but pointed at separate repositories, cnfa for permissions and androidusbtest for USB.
Everything else Android normally offers through the SDK is reached by marshalling calls across the JNI. The README points at CNFGEGLDriver.c in the cntools/rawdraw repository as the reference for doing a large amount of that work from C without returning to Java or Kotlin. So the Java-free claim is about your own source tree, not about the boundary with the platform. Underneath, the boundary is still there.
make push run is the entire first-use loop
On Linux the prerequisites are a headless JDK and adb:
sudo apt install openjdk-17-jdk-headless adbThen clone the repository with its submodules, since rawdraw and cnfa are pulled in by .gitmodules:
git clone https://github.com/cnlohr/rawdrawandroid --recurse-submodules
cd rawdrawandroidSigning is part of the setup, not a later chore. The Makefile carries a keystore target, and the README lists it as step 10 of the Linux sequence:
make keystoreAfter enabling developer mode and USB debugging on the device, the demo runs with:
make push runThe Makefile reaches adb through an overridable ADB variable and pushes the package built from test.c. On a machine that already has the platform tools on PATH, this is the shortest complete path from clone to a running APK in the README.
Every override in the Makefile is something you can get wrong
The build is readable precisely because it is also unopinionated, which pushes responsibility onto the reader. APPNAME defaults to cnfgtest and LABEL derives from it. The header comment above APPNAME is blunt about it: the project name must be overridden, and so must the signature file and the manifest. PACKAGENAME defaults to org.yourorg.$(APPNAME), a placeholder that has to change before anything ships.
SRC points at test.c. Swap it for your own file and the whole rest of the toolchain still works, because the glue is added for you. ANDROIDVERSION defaults to 30 and ANDROIDTARGET follows it. A comment records that the author tried Android 22, 24, 28, 29, 30, 32 and 34, and notes that setting ANDROIDVERSION to 22 means your app should (though not necessarily) support all the way back to Android 22.
CFLAGS and LDFLAGS carry a size-oriented default, with -Os, section garbage collection, a stripped binary and a linker map written to output.map in BUILD_DIR. Anyone wanting debug symbols will have to override those defaults.
Where the OpenXR branch and the NDK version assumption bite
Two places in the repository will stop a first build in ways the README does not smooth over.
The first is the NDK path. Debugging instructions reference a hardcoded clang 19 layout for lldb-server. The copy and connect steps depend on your SDK layout matching that version, and the run-as calls use org.yourorg.cnfgtest as the package name, which only holds if you did not override PACKAGENAME.
The second is the Windows and WSL path. Most testing was done on Linux, with only cursory testing in Windows by a contributor. The README prefers the WSL instructions over the Android Studio install and calls the graphical route heavier, noting it installs a lot more and can take 6 GB of disk.
A third is commercial distribution. The disclaimer states plainly that no app has ever been released on the app store by the author and that there may be a fundamental issue with using this toolset for commercial apps. That sentence belongs in any adoption decision.
What RawDrawAndroid gives up against the standard Android route
The real alternative is the ordinary Android project: Android Studio, Gradle, Kotlin or Java, and the Play Console. The difference in approach is not quality, it is ownership. Gradle owns dependency resolution, build variants, signing configuration and a manifest merged from many sources. RawDrawAndroid hands you a single Makefile where all of that is one line each, and nothing in it manages them for you.
What you give up is concrete. There is no dependency resolution, so no Compose, no AndroidX, no Kotlin standard library and no Play Services. Publishing goes through the Play Console's own signing flow, which the README treats as a separate, multi-step procedure built around a Java keystore. Updates, staged rollout and store listing metadata are all handled by tools this project does not include.
For a demo, a sensor logger, a USB device test or an offline APK, that trade is worth it. For anything with a login, a push channel or a store publishing process, the trade inverts quickly.
Support runs through a private Discord and an untagged tree
The README's own support note adds context rather than reducing it. There is a Discord, it is not public, and access requires messaging the author directly with a reason and waiting for an invite. No GitHub releases are published, so there is no tagged version to pin against and no changelog to read when something changes. The last push was on 2026-09-28, so the code in the tree is current even though nothing around it is versioned.
For a project whose build depends on your specific NDK layout and SDK version, a private channel is a thin support surface. Worth pairing with a local fork so your own fixes do not depend on anyone else's availability.
Editorial conclusion
Adopt it if you write C, want an APK you can read end to end, and can accept owning your own manifest, keystore and dependency list by hand. Do not adopt it if your work depends on Play Console publishing tools, AndroidX or Play Services, or if a team expects a conventional Gradle project layout that any hire can open without help. Verify first that make push run works against a device on the API level you care about, since the default ANDROIDVERSION is 30 and the SDK search path may not match your machine. After that, read test.c and android_native_app_glue.c before writing anything, because those two files, not the README, define what your app can actually reach.
Frequently asked questions
What language do I need to write a rawdrawandroid app?
C. The repository compiles test.c together with android_native_app_glue.c, and the Makefile's SRC variable points at a C source file by default. Platform features are reached by marshalling across the JNI rather than by writing Java.
How small is the rawdrawandroid APK?
About 25kB with API 26, and about 45kB at API 30 so the package can carry ARM64 and ARM32 together. The increase comes from supporting the second architecture rather than from framework growth.
How do I build and run a rawdrawandroid app?
Run make push run after enabling developer mode and USB debugging on the device, with adb available on PATH. The Makefile declares both push and run as .PHONY targets.
Can I publish a rawdrawandroid app to Google Play?
The README does not claim this has been done. Its disclaimer states the author has never released an app on the app store and that there may be a fundamental issue with the toolset for commercial apps.
What do I change in the rawdrawandroid Makefile before shipping?
APPNAME, PACKAGENAME, the signature file and the manifest all need overriding, as a comment in the Makefile warns. PACKAGENAME defaults to the placeholder org.yourorg.cnfgtest and SRC defaults to test.c.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cnlohr-rawdrawandroid)Star history chart for your README
[](https://hysenlabs.com/projects/cnlohr-rawdrawandroid)Was this useful?