android ndk-samples: a catalogue of native code, with a warning attached
Android NDK samples with Android Studio
At a glance
- What is it?
- Thirty-odd sample apps covering JNI, Vulkan, OpenGL, audio and more, with an unusually candid README that tells you not to copy them into production and points you at the project wizard instead.
- Who is it for?
- This repository is best understood as documentation that happens to compile. Its own README says the samples make sacrifices for succinctness and should not be used as the starting point for a production app, and it is unusually direct about pointing you at the Android Studio New Project wizard and Now in Android instead.
- Can I use it commercially?
- Yes. Apache-2.0 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 12 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 October 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The README tells you not to copy these samples
Most sample repositories quietly imply you could ship from them. This one says the opposite, in a section headed I just want something to copy from as a starting point. The claim is that the samples aim to demonstrate individual NDK APIs but often make sacrifices to be succinct that make them unsuitable for a production app. It acknowledges this is gradually changing and then says, in as many words, that for now you should not do this.
The alternatives it names are useful. Now in Android is called an excellent resource for production quality apps in general, with the caveat that it does not touch NDK specific issues. For that gap it points at a third-party `ndk-app-template`. The recommendation that follows is the one most people should take: create a new app with the Android Studio New Project wizard, then use those resources and these samples as a reference.
Two templates are singled out. The Native C++ template suits typical applications that need some C++ via JNI. The Game Activity template suits game-like apps that do not use the Android UI at all and render their own with OpenGL or Vulkan.
Given that framing, the right way to read this repository is as a reference for NDK integration patterns rather than as code to inherit. Ten and a half thousand stars and four thousand forks say plenty of people have looked, and only 26 open issues suggests most of them got what they came for.
Building it: clone, open, install CMake by hand
The build instructions are five steps and the third one is a manual action you would not expect. Clone the repository, open the whole project in Android Studio, then install CMake 4.1.0 through the SDK Manager. The README explains that this has to be done manually until a specific issue tracker bug is fixed, and it names the issue number so you can check whether it still applies.
After that you select the sample you want from the top bar, which may require a Gradle sync first, and press the play button.
./gradlew build
./gradlew tasks
./gradlew :camera:basic:tasksThe command line path exists for anyone who prefers it. `./gradlew build` builds everything, with `.\gradlew.bat` as the Windows equivalent. `./gradlew tasks` lists individual tasks, and running `tasks` against one sample directory shows just that sample, which the README illustrates with the `camera/basic` app.
The layout itself is explained in a separate `ARCHITECTURE.md`, and the root tree shows why that file is needed. Directories are grouped by theme rather than alphabet: `camera/`, `audio-echo/`, `native-audio/`, `native-codec/`, `native-media/`, `native-midi/`, `nn-samples/`, `prefab/`, `sanitizers/`, `unit-test/`, `vectorization/` and `orderfile/` for the version script behaviour, alongside `build-logic/` and `cmake/` for the shared build machinery.
The two best practices the README insists on
The README admits there is no central place to discuss best practices in the code, so it discusses two of them in the README itself. Both are quiet killers if you skip them.
The first is `RegisterNatives`. The preference is for registering natives through `JNI_OnLoad()` rather than the name-based matching that Studio's New Project wizard generates, which produces functions following the pattern `JNIEXPORT void JNICALL Java_com_etc_ClassName_methodName()`. The README concedes that name-based matching makes for a shorter demo when there are only a handful of functions, but points at the JNI tips guide for the disadvantages. The pattern is arguably more work up front and much easier to refactor later, since nothing in C++ carries the Java package name.
The second is version scripts, and the language here is the strongest opinion in the README: every app library in the repository is built with one, and there are no good reasons to not use a version script for your NDK code. A version script lists which symbols the library exports and hides the rest. It works like `-fvisibility=hidden` but goes further, because it can hide symbols in static libraries too.
The payoff the README spells out is in three parts. Hiding symbols means smaller binaries that load faster, since there are fewer relocations and LTO has more to work with. Same-library calls skip the PLT, which makes them faster. The file naming convention is `lib<name>.map.txt`, where `<name>` matches the library name passed to `add_app_library()` in that sample's `CMakeLists.txt`, and the plumbing that consumes the script lives in `add_app_library()` in `cmake/AppLibrary.cmake`. The `orderfile/` sample directory exists to demonstrate this.
What is actually in the catalogue
The directory list is the sample list, and it spans the range of things the NDK is for.
At the entry level are `hello-jni/` and `hello-jniCallback/`, which are the traditional starting points for the JNI basics including callbacks from native code. `base/` and `unit-test/` cover GoogleTest-style native testing and the build wiring around it. `exceptions/` deals with C++ exception handling across the JNI boundary, and `sanitizers/` shows the address and undefined behaviour sanitizers configured for a real app.
Graphics is the biggest cluster. `hello-gl2/` is the OpenGL ES 2.0 version of hello world, `gles3jni/` moves to OpenGL ES 3.x, `hello-vulkan/` does the equivalent for Vulkan, and `teapots/`, `bitmap-plasma/`, `sensor-graph/` and `san-angeles/` are more elaborate renderers. `native-activity/` is the case where the app hands the whole surface to native code rather than hosting a view.
Audio and media have their own group: `audio-echo/`, `hello-oboe/` for the Oboe library, `native-audio/`, `native-codec/` for platform codecs, `native-media/` for MediaCodec, and `native-midi/`. `nn-samples/` covers neural network APIs, `prefab/` covers publishing native dependencies as prefab packages, and `vectorization/` covers SIMD.
Audio is where the hardware caveat bites hardest. Several of these samples need specific device support, so an emulator is a poor test bed for anything involving Oboe or low-latency audio.
Where to send which kind of bug
The support section is more useful than it looks, because the three bug categories point at three different trackers and picking the wrong one is how issues get lost.
Problems with the samples themselves go to the googlesamples/android-ndk issue tracker, which is a separate repository from this one. Problems with the OS APIs go to b.android.com, usually the Framework component, because a sample behaving oddly may be reporting a platform bug rather than a sample bug. Problems with the NDK as a compiler or build system go to the android/ndk tracker.
For questions rather than bugs, the README recommends four venues with a clear preference order. The NDK mailing list on Google Groups is best if you are not sure where else to ask. The Discussions tab on this repository is best for questions about the samples specifically. The NDK's own Discussions tab is best for the compilers and build systems. Stack Overflow with the android tag is the fallback.
The project also links out to four related sample sets that fill gaps this one does not cover: the Google Play Games C++ samples, the Google Android Vulkan tutorials, the Android Vulkan API basic samples, and the Android High Performance Audio samples. If what you need is Vulkan from a tutorial angle or high performance audio beyond what Oboe shows here, those are the next places to look.
Licensing is the standard Apache 2.0, copyright 2015 The Android Open Source Project, so the code is usable in commercial work with attribution.
A repository that is documentation with a compiler attached
It is worth being precise about what this repository is for, because the star count invites a reading it does not support. It is not a starter kit. It is not a best practice guide, since the README says the practices are scattered and there is no central place for them. It is a set of working, compileable demonstrations of specific NDK surfaces, plus a README unusually willing to tell you it is not enough.
That candour is its main virtue. A sample repository that warns you off using it is rarer than it should be, and the specific recommendation, start from the New Project wizard and consult these as reference, saves people from inheriting a project structured around whichever NDK feature happened to interest the sample author.
The two practices it does push, `RegisterNatives` and version scripts, are the items worth carrying into whatever you build. Both are easy to add later and annoying to retrofit, both affect things you can measure in binary size and startup time, and both are the kind of thing a sample that optimizes for brevity will skip. The `orderfile/` sample is where the version script idea becomes concrete.
The practical entry point for most readers is `hello-jni/`, and the most useful reading is `ARCHITECTURE.md` after that, since it explains the repository layout the README deliberately defers. The last push to `main` was on 2026-09-25, so the examples track current NDK versions even as the overall structure has stayed stable for years.
Editorial conclusion
This repository is best understood as documentation that happens to compile. Its own README says the samples make sacrifices for succinctness and should not be used as the starting point for a production app, and it is unusually direct about pointing you at the Android Studio New Project wizard and Now in Android instead. What it does offer that those do not is a broad, honest spread of native integration points, from a single hello-jni to Oboe, MIDI, codecs and neural network samples, plus two best practices that are easy to skip past: registering natives in JNI_OnLoad and hiding symbols with a version script. Read it as a reference for how the NDK is meant to be used, and start a real project from the wizard.
Frequently asked questions
Can I use these NDK samples as the starting point for a production app?
No, and the README says so explicitly. The samples aim to demonstrate individual NDK APIs and often make sacrifices for succinctness that make them unsuitable for a production app. It recommends the Android Studio New Project wizard instead, using the Native C++ template for typical apps or the Game Activity template for apps that render their own UI with OpenGL or Vulkan, and treating these samples as reference.
Why does the build require manually installing CMake?
You have to install CMake 4.1.0 through the SDK Manager by hand, because the README says it must be done manually until a referenced issue tracker bug is fixed. After that, open the whole project in Android Studio, pick a sample from the top bar, possibly sync Gradle first, and run it, or build everything from the command line with `./gradlew build`.
What is a version script and why does the NDK prefer RegisterNatives?
A version script lists the symbols a library exports and hides everything else, producing smaller, faster-loading binaries with fewer relocations, and letting same-library calls skip the PLT. Each sample ships one as `lib<name>.map.txt`. Separately, the samples register their JNI functions in `JNI_OnLoad()` via `RegisterNatives()` instead of relying on name-based exports like `Java_com_etc_ClassName_methodName`.
Where should I report a bug in an NDK sample?
It depends on the kind of problem. Sample problems go to the googlesamples/android-ndk issue tracker, OS API problems to b.android.com under the Framework component, and NDK compiler or build system problems to the android/ndk tracker. For questions rather than bugs, the Discussions tab here is best for the samples themselves and the NDK mailing list is the fallback when you are not sure.
Which ndk-samples directory should I start reading from?
`hello-jni/` is the entry point for JNI basics, with `hello-jniCallback/` covering callbacks from native code. For graphics there is `hello-gl2/`, `gles3jni/`, `hello-vulkan/` and `native-activity/`, while audio, codecs and media live under `audio-echo/`, `hello-oboe/`, `native-audio/`, `native-codec/`, `native-media/` and `native-midi/`. Read `ARCHITECTURE.md` for how the repository is laid out.
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/android-ndk-samples)