NDK Android: шта је то, Native Development Kit и JNI за C++

Аутор: IT Sectr Објављено: 2026-02-09 Време читања: 10 мин

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 — алат за компајлирање C/C++ кода у native библиотеке под Android-ом.
  • JNI — интерфејс интеракције између виртуелне машине Java/Kotlin и native кода.
  • CMake — основни систем изградње за NDK пројекте, подесив кроз CMakeLists.txt.
  • ABI — циљна архитектура процесора (arm64-v8a, armeabi-v7a, x86_64) за коју се гради библиотека.
  • NDK није потребан за већину Android апликација и примењује се само у задацима са високим захтевима за перформансама.

Шта је NDK

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

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 vs SDK: када је потребан native код

Избор између 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 и NDK по критеријумима

КритеријумSDK (Kotlin/Java)NDK (C/C++)
ПерформансеСредње (JIT/AOT компајлирање)Високе (машински код)
Кашњење звука50–200 ms5–15 ms кроз Oboe
3D графикаКроз Canvas/OpenGL Kotlin APIVulkan/OpenGL директно
Сложеност развојаНискаВисока (управљање меморијом, JNI)
Преносивост кодаСамо AndroidLinux, Windows, macOS, iOS
Величина APKМинимална+1–10 MB по библиотеци

Архитектура NDK: алати и библиотеке

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

text
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 датотека

Native API Android-а

Кроз 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: како Kotlin позива C++

JNI (Java Native Interface) — стандардни механизам позивања native кода из виртуелне машине Java/Kotlin. Програмер декларише у Kotlin спољну функцију са кључном речи external и повезује .so библиотеку кроз System.loadLibrary. На страни C++, функција се декларише коришћењем конвенције именовања JNI која кодира пакет и име класе.

Декларација native функције у Kotlin

kotlin
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++"

Имплементација JNI функције у C++

cpp
#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;
}

Подешавање CMakeLists.txt за NDK

CMake — основни систем изградње за NDK, који је заменио застарели ndk-build. Датотека CMakeLists.txt описује изворне датотеке, библиотеке и флагове компајлирања. Android Studio аутоматски позива CMake при изградњи пројекта ако је подешен externalNativeBuild у build.gradle. CMake генерише make датотеке за сваки циљни ABI и компајлира native код паралелно.

Пример CMakeLists.txt за native библиотеку

cmake
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)

Подешавање build.gradle за NDK

groovy
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 и вишeплатформска градња

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.

Одређивање ABI уређаја у native коду

cpp
#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-v8aARMv8-A64-битниСкоро сви модерни телефони
armeabi-v7aARMv7-A32-битниСтари уређаји (до 2020)
x86_64x86-6464-битниЕмулатор, Chromebook
x86x86 IA-3232-битниЗастарели емулатори

Примери native кода у C++

Размотримо практичан пример: математичка библиотека за рад са бројевима са покретним зарезом. Native код у C++ обавља израчунавања ефикасније од Kotlin-а захваљујући директном приступу NEON инструкцијама ARM и одсуству провера граница низова у runtime. Овај пример демонстрира типичан образац употребе NDK — изношење тешких израчунавања у native слој.

Математичке операције у native коду

cpp
#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 кода

За отклањање грешака у native коду користите макро __android_log_print из библиотеке android/log.h. Поруке се појављују у Logcat-у поред Java/Kotlin логова. Ниво логирања (ANDROID_LOG_DEBUG, ANDROID_LOG_ERROR) помаже у филтрирању порука.

cpp
#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");
}

Често постављана питања

Да ли је обавезно користити NDK за Android развој?

Не. За већину апликација довољан је SDK у Kotlin. NDK је потребан за високоперформансне задатке: обрада звука/видеа у реалном времену, 3D графика, криптографија или поновна употреба постојећих C/C++ пројеката.

Који компајлер користи NDK?

NDK користи Clang из LLVM toolchain-а. Од NDK r23 GCC је потпуно уклоњен. Clang унакрсно компајлира код за све Android ABI: arm64-v8a, armeabi-v7a, x86_64, x86.

Шта је ABI у контексту NDK?

ABI (Application Binary Interface) — формат машинског кода који одређује компатибилност са процесором. NDK гради .so библиотеке за сваки ABI посебно. arm64-v8a — главни ABI за модерне Android уређаје.

Може ли се C++ код отклањати кроз NDK?

Да. Android Studio подржава LLDB — дебагер native кода. Могу се постављати breakpoint-ови у C++ датотекама, прегледати променљиве и стек позива. За рад су потребни NDK и LLDB прикључак.

Како NDK утиче на величину APK?

Свака native библиотека додаје 100 KB — неколико MB у APK. За сваки ABI потребна је засебна .so библиотека. Android App Bundle испоручује кориснику само одговарајућу архитектуру, смањујући величину инсталације.

Закључак

  • NDK — скуп алата за унакрсно компајлирање C/C++ кода у native библиотеке под Android-ом кроз компајлер Clang.
  • JNI — интерфејс који повезује Kotlin/Java са native кодом кроз кључну реч external и конвенцију именовања функција.
  • CMake — основни систем изградње NDK, подесив кроз датотеку CMakeLists.txt и externalNativeBuild у Gradle-у.
  • ABI одређује архитектуру процесора — arm64-v8a, armeabi-v7a, x86_64. Сваки ABI захтева засебну градњу библиотеке.
  • Користите NDK само за задатке који захтевају високе перформансе: игре, звук, графика, криптографија, машинско учење на уређају.
  • Google Play подржава ABI раздвајање кроз App Bundle: корисник добија само библиотеку за архитектуру свог уређаја.
  • Native библиотеке значајно повећавају APK, али обезбеђују максималне перформансе и ниско кашњење за критичне операције.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође