NDK (Native Development Kit) — е инструментариум за писане на част от приложението на C и C++ за Android. За разлика от обикновения Android SDK, NDK компилира кода в native библиотеки (.so), които работят директно с процесора без слой на виртуална машина. Според Google NDK Guides, 2026, NDK се използва за високопроизводителни изчисления, игри, обработка на аудио и преизползване на съществуващи C/C++ проекти. JNI (Java Native Interface) свързва native кода с Kotlin и Java.
Основни моменти
NDK (Native Development Kit) — е набор от инструменти за кръстосано компилиране на C и C++ код в изпълними библиотеки за Android. NDK включва компилатора Clang, стандартната библиотека libc++, заглавни файлове на Android API и помощни програми за изграждане. Разработчикът пише native код на C или C++, компилира го в .so файлове (shared objects) и го свързва с приложението чрез JNI.
NDK не замества Android SDK, а го допълва. Целият UI, lifecycle и системни услуги остават в Kotlin или Java. Native кодът решава тесни задачи: математически изчисления, криптография, кодеци, физика в игри. Google препоръчва използването на NDK само когато SDK не осигурява необходимата производителност или достъп до хардуерни възможности.
Историята на NDK започва от 2009 г. (NDK r1). През това време инструментите преминаха от експериментален набор от скриптове до зряла система с поддръжка на CMake, LLDB дебъгване и профилиране. Към 2026 г. актуалната версия е NDK r27 с Clang 19, пълна поддръжка на C++20 и libc++ като единствена стандартна библиотека.
NDK предоставя на разработчика достъп до нисконивови възможности на Android чрез native API. Основните сценарии за използване включват: работа с OpenGL ES и Vulkan за 3D графика, обработка на аудио чрез Oboe, криптографски операции чрез BoringSSL и NEON оптимизации за ARM. Всички тези API са достъпни от C/C++ и изискват NDK за компилиране.
Освен това NDK позволява преизползване на съществуващи C/C++ библиотеки без преписване на Kotlin. Това е особено важно за проекти с дългогодишна история на C++ — игрови двигатели (Unity, Unreal Engine), библиотеки за компютърно зрение (OpenCV) или криптографски пакети (OpenSSL). В такива случаи NDK спестява години разработка.
| Компонент | Предназначение |
|---|---|
| Clang | Компилатор C/C++ с поддръжка на C++20 |
| libc++ | Стандартна библиотека C++ (единствена в NDK r27) |
| CMake | Система за изграждане на native библиотеки |
| LLDB | Дебъгер на native код в Android Studio |
| ndk-build | Остаряла система за изграждане (заместена от CMake) |
Изборът между NDK и чист SDK зависи от задачата. Android SDK предоставя готови Java/Kotlin API за 90% от сценариите — работа с мрежа, файлове, известия, камера. NDK се свързва, когато тези API не осигуряват необходимата производителност или функционалност. Например, обработка на аудио в реално време чрез SDK е възможна, но със закъснение от 50–200 ms, докато native библиотека чрез Oboe намалява закъснението до 5–15 ms.
Размер на APK — друг фактор. Добавянето на NDK увеличава размера на приложението, тъй като всяка ABI архитектура изисква отделна .so библиотека. Използването на Android App Bundle (AAB) обаче смекчава проблема: Google Play доставя на потребителя само библиотеката за неговата архитектура. Типичен native проект добавя 1–10 MB към размера на инсталацията на устройството.
| Критерий | SDK (Kotlin/Java) | NDK (C/C++) |
|---|---|---|
| Производителност | Средна (JIT/AOT компилиране) | Висока (машинен код) |
| Закъснение на аудио | 50–200 ms | 5–15 ms чрез Oboe |
| 3D графика | Чрез Canvas/OpenGL Kotlin API | Директно Vulkan/OpenGL |
| Сложност на разработка | Ниска | Висока (управление на памет, JNI) |
| Преносимост на код | Само Android | Linux, Windows, macOS, iOS |
| Размер на APK | Минимален | +1–10 MB на библиотека |
NDK се инсталира отделно от Android SDK чрез SDK Manager. Вътре в директорията на NDK се намират toolchain (компилатори), платформени библиотеки, заглавни файлове и помощни програми. NDK Toolchain включва Clang за кръстосано компилиране за всички целеви ABI: arm64-v8a, armeabi-v7a, x86_64 и x86. Компилаторът автоматично избира правилната архитектура въз основа на флагове на CMake или ndk-build.
Android API за native код са представени от заглавни файлове в директорията sysroot/usr/include. Там се намират декларации за всички API, достъпни в native код: native_activity.h за lifecycle на Activity, input.h за входни събития, sensor.h за сензори. Свързването на тези заглавни файлове предоставя достъп до хардуерни възможности без JNI слой.
ndk/
toolchains/
llvm/prebuilt/windows-x86_64/
bin/ // Clang, ld, llvm-profdata
sysroot/ // Заглавни файлове на Android API
platforms/
android-26/ // libc, libm, libdl за API 26
android-34/
sources/
cxx-stl/ // Заглавни файлове на libc++
build/
cmake/ // CMake toolchain файл
Чрез NDK са достъпни следните групи native API: Native App Glue (управление на lifecycle на Activity от C), OpenGL ES 3.2 и Vulkan 1.3 (графика), Oboe (аудио с ниско закъснение), Neural Networks API (машинно обучение на устройството). Всяко API има заглавен файл и статична/динамична библиотека в състава на NDK.
За работа с native API не е необходим JNI — функциите се извикват директно от C/C++ код. Въпреки това, за взаимодействие с UI в Kotlin все още е необходим JNI. Такава хибридна архитектура се среща в игрови двигатели: графика и физика на C++ (чрез Vulkan), меню и UI на Kotlin (чрез Jetpack Compose).
JNI (Java Native Interface) — стандартният механизъм за извикване на native код от виртуалната машина Java/Kotlin. Разработчикът декларира в Kotlin външна функция с ключовата дума external и свързва .so библиотеката чрез System.loadLibrary. От страна на C++, функцията се декларира с помощта на конвенцията за именуване на JNI, която кодира пакета и името на класа.
class NativeBridge {
companion object {
init {
System.loadLibrary("native-lib")
}
}
external fun stringFromJNI(): String
external fun fibonacci(n: Int): Long
external fun processBuffer(data: ByteArray): ByteArray
}
// Използване в код
val bridge = NativeBridge()
println(bridge.stringFromJNI()) // "Hello from C++"
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_app_NativeBridge_stringFromJNI(
JNIEnv* env, jobject /* this */) {
std::string hello = "Hello from C++ NDK";
return env->NewStringUTF(hello.c_str());
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_example_app_NativeBridge_fibonacci(
JNIEnv* env, jobject /* this */, jint n) {
if (n <= 1) return n;
jlong a = 0, b = 1;
for (int i = 2; i <= n; i++) {
jlong temp = a + b;
a = b;
b = temp;
}
return b;
}
CMake — основната система за изграждане за NDK, която замени остарелия ndk-build. Файлът CMakeLists.txt описва изходните файлове, библиотеките и флаговете за компилиране. Android Studio автоматично извиква CMake при изграждане на проекта, ако externalNativeBuild е конфигуриран в build.gradle. CMake генерира make файлове за всеки целеви ABI и компилира native код паралелно.
cmake_minimum_required(VERSION 3.22.1)
project("nativelib")
# Свързване на заглавни файлове
include_directories(src/main/cpp/include)
# Създаване на native библиотека
add_library(
native-lib
SHARED
src/main/cpp/native-lib.cpp
src/main/cpp/math_utils.cpp
src/main/cpp/audio_processor.cpp
)
# Свързване на системни библиотеки на Android
target_link_libraries(
native-lib
android
log
OpenSLES
# libc++ се свързва автоматично
)
# Флагове за оптимизация
target_compile_options(native-lib PRIVATE -O3 -Wall -Wextra)
android {
defaultConfig {
ndk {
// Целеви ABI за изграждане
abiFilters "arm64-v8a", "armeabi-v7a", "x86_64"
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
version "3.22.1"
}
}
buildTypes {
release {
externalNativeBuild {
cmake {
arguments "-DCMAKE_BUILD_TYPE=Release"
}
}
}
}
}
ABI (Application Binary Interface) — формат на машинен код, който определя съвместимостта с процесора на устройството. Всяка ARM или x86 архитектура има свой ABI. NDK компилира native код отделно за всяко указано ABI. Най-разпространените ABI през 2026 г.: arm64-v8a (99% от съвременните устройства), armeabi-v7a (стари 32-битови устройства), x86_64 (емулатор и Chromebook).
Посочването на abiFilters в build.gradle ограничава изграждането само до необходимите архитектури, което съкращава времето за компилиране. За Google Play се препоръчва включването на всички ABI, с които библиотеката е съвместима — това гарантира работа на всички устройства. Google Play Console позволява конфигуриране на доставка на ABI-специфични APK чрез App Bundle.
#include <jni.h>
#include <android/api-level.h>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_app_NativeBridge_getABIInfo(
JNIEnv* env, jobject /* this */) {
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
return env->NewStringUTF("armeabi-v7a");
#endif
#elif defined(__aarch64__)
return env->NewStringUTF("arm64-v8a");
#elif defined(__x86_64__)
return env->NewStringUTF("x86_64");
#elif defined(__i386__)
return env->NewStringUTF("x86");
#endif
return env->NewStringUTF("unknown");
}
| ABI | Архитектура | Битност | Устройства |
|---|---|---|---|
| arm64-v8a | ARMv8-A | 64-битов | Почти всички съвременни телефони |
| armeabi-v7a | ARMv7-A | 32-битов | Стари устройства (до 2020 г.) |
| x86_64 | x86-64 | 64-битов | Емулатор, Chromebook |
| x86 | x86 IA-32 | 32-битов | Остарели емулатори |
Нека разгледаме практически пример: математическа библиотека за работа с числа с плаваща запетая. Native кодът в C++ извършва изчисления по-ефективно от Kotlin, благодарение на директния достъп до NEON ARM инструкции и липсата на проверки на границите на масивите по време на изпълнение. Този пример демонстрира типичния модел на използване на NDK — прехвърляне на тежки изчисления в native слоя.
#include <jni.h>
#include <cmath>
#include <vector>
extern "C" JNIEXPORT jfloatArray JNICALL
Java_com_example_app_NativeBridge_normalizeArray(
JNIEnv* env, jobject, jfloatArray input) {
jsize len = env->GetArrayLength(input);
jfloat* elements = env->GetFloatArrayElements(input, nullptr);
// Изчисляваме средна стойност и стандартно отклонение
float sum = 0.0f, sumSq = 0.0f;
for (jsize i = 0; i < len; i++) {
sum += elements[i];
sumSq += elements[i] * elements[i];
}
float mean = sum / len;
float stddev = std::sqrt(sumSq / len - mean * mean);
// Нормализация: (x - mean) / stddev
jfloat* result = new jfloat[len];
for (jsize i = 0; i < len; i++) {
result[i] = (elements[i] - mean) / stddev;
}
env->ReleaseFloatArrayElements(input, elements, JNI_ABORT);
jfloatArray output = env->NewFloatArray(len);
env->SetFloatArrayRegion(output, 0, len, result);
delete[] result;
return output;
}
За дебъгване на native код използвайте макроса __android_log_print от библиотеката android/log.h. Съобщенията се появяват в Logcat до Java/Kotlin логовете. Нивото на логиране (ANDROID_LOG_DEBUG, ANDROID_LOG_ERROR) помага за филтриране на съобщения.
#include <android/log.h>
#define LOG_TAG "NativeLib"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
extern "C" JNIEXPORT void JNICALL
Java_com_example_app_NativeBridge_processData(
JNIEnv* env, jobject, jint count) {
LOGD("Processing %d items", count);
for (int i = 0; i < count; i++) {
// Тежка обработка
LOGD("Item %d processed", i);
}
LOGD("Processing complete");
}
Често задавани въпроси
Не. За повечето приложения е достатъчен SDK в Kotlin. NDK е необходим за високопроизводителни задачи: обработка на аудио/видео в реално време, 3D графика, криптография или преизползване на съществуващи C/C++ проекти.
NDK използва Clang от LLVM toolchain. От NDK r23 нататък GCC е напълно премахнат. Clang кръстосано компилира код за всички Android ABI: arm64-v8a, armeabi-v7a, x86_64, x86.
ABI (Application Binary Interface) — формат на машинен код, определящ съвместимостта с процесора. NDK изгражда .so библиотеки за всяко ABI отделно. arm64-v8a — основното ABI за съвременни Android устройства.
Да. Android Studio поддържа LLDB — дебъгер за native код. Могат да се поставят breakpoint-и в C++ файлове, да се преглеждат променливи и стекът на извикванията. За работа са необходими NDK и LLDB приставка.
Всяка native библиотека добавя 100 KB — няколко MB към APK. За всяко ABI е необходима отделна .so библиотека. Android App Bundle доставя на потребителя само подходящата архитектура, намалявайки размера на инсталацията.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също