The Android NDK lets you build parts of an app in C and C++ and call them from Kotlin/Java through JNI. You reach for it for performance-critical code, reusing existing native libraries, or low-level access — and it is exactly the layer React Native itself uses to bridge JavaScript to the platform.
Key takeaways
- Use the NDK for CPU-heavy code, existing C/C++ libraries, or low-level needs — not by default.
- JNI is the bridge between managed Kotlin/Java and native code.
- CMake (or ndk-build) compiles the native sources into the APK.
When the NDK is worth it
Most apps never need the NDK — Kotlin is fast enough and far easier to maintain. The justified cases are signal/image processing, cryptography, game engines, or reusing a mature C/C++ library. Native code adds build complexity and platform-specific risk, so use it deliberately.
JNI and the build
JNI defines how Kotlin/Java calls into native functions and back. You declare external functions, implement them in C/C++, and load the compiled library at runtime. CMake, configured in your Gradle module, compiles the sources for each ABI and packages them into the APK or App Bundle.
Relevance to React Native
React Native's own architecture (JSI, the bridge, Hermes) is built on native C++ that talks to Android through this same JNI layer. Understanding the NDK demystifies what happens under a React Native app and helps when debugging native crashes or building advanced native modules.