NDK Android: mi ez, Native Development Kit és JNI C++-hoz

Szerző: IT Sectr Megjelenés: 2026-02-09 Olvasási idő: 10 perc

NDK (Native Development Kit) — egy eszközkészlet az alkalmazás egy részének C és C++ nyelven történő megírásához Android alá. Ellentétben a szokásos Android SDK-val, az NDK natív könyvtárakká (.so) fordítja a kódot, amelyek közvetlenül a processzoron futnak a virtuális gép rétege nélkül. A Google NDK Guides, 2026 szerint az NDK-t nagy teljesítményű számításokhoz, játékokhoz, hangfeldolgozáshoz és meglévő C/C++ projektek újrafelhasználásához használják. JNI (Java Native Interface) összeköti a natív kódot Kotlinnal és Javával.

Főbb pontok

  • NDK — eszközkészlet C/C++ kód natív könyvtárakká fordításához Android alá.
  • JNI — interfész a Java/Kotlin virtuális gép és a natív kód közötti interakcióhoz.
  • CMake — az NDK projektek elsődleges build rendszere, a CMakeLists.txt-n keresztül konfigurálható.
  • ABI — a processzor célarchitektúrája (arm64-v8a, armeabi-v7a, x86_64), amelyre a könyvtár épül.
  • NDK nem szükséges a legtöbb Android-alkalmazáshoz, és csak magas teljesítményigényű feladatokban alkalmazzák.

Mi az NDK

NDK (Native Development Kit) — egy eszközkészlet C és C++ kód keresztfordításához végrehajtható könyvtárakká Android alá. Az NDK tartalmazza a Clang fordítót, a libc++ szabványos könyvtárat, az Android API fejlécfájlokat és build segédprogramokat. A fejlesztő natív kódot ír C vagy C++ nyelven, .so fájlokká (shared objects) fordítja, és JNI-n keresztül csatlakoztatja az alkalmazáshoz.

Az NDK nem helyettesíti az Android SDK-t, hanem kiegészíti azt. A teljes UI, lifecycle és rendszerszolgáltatások Kotlinban vagy Javában maradnak. A natív kód szűk feladatokat old meg: matematikai számítások, kriptográfia, kodekek, fizika játékokban. A Google ajánlja az NDK használatát csak akkor, ha az SDK nem biztosítja a szükséges teljesítményt vagy hozzáférést a hardveres képességekhez.

Az NDK története 2009-ben kezdődik (NDK r1). Ez idő alatt az eszközök egy kísérleti szkriptkészletből egy érett rendszerré fejlődtek CMake, LLDB hibakeresés és profilozás támogatással. 2026-ra a jelenlegi verzió NDK r27 Clang 19-cel, teljes C++20 támogatással és libc++-vel, mint egyetlen szabványos könyvtárral.

Az NDK fő képességei

Az NDK hozzáférést biztosít a fejlesztőnek az Android alacsony szintű képességeihez natív API-ken keresztül. A fő használati forgatókönyvek közé tartozik: munka OpenGL ES és Vulkan segítségével 3D grafikához, hangfeldolgozás Oboe-n keresztül, kriptográfiai műveletek BoringSSL-en keresztül és NEON optimalizálások ARM-hez. Mindezek az API-k elérhetők C/C++-ból, és NDK-t igényelnek a fordításukhoz.

Emellett az NDK lehetővé teszi meglévő C/C++ könyvtárak újrafelhasználását anélkül, hogy Kotlinra kellene átírni őket. Ez különösen fontos a C++-ban hosszú múltra visszatekintő projekteknél — játékmotorok (Unity, Unreal Engine), számítógépes látáskönyvtárak (OpenCV) vagy kriptográfiai csomagok (OpenSSL). Ilyen esetekben az NDK éveket spórol a fejlesztésből.

KomponensRendeltetés
ClangC/C++ fordító C++20 támogatással
libc++Szabványos C++ könyvtár (egyetlen az NDK r27-ben)
CMakeNatív könyvtárak build rendszere
LLDBNatív kód hibakereső az Android Studio-ban
ndk-buildElavult build rendszer (CMake váltotta fel)

NDK vs SDK: mikor szükséges a natív kód

A választás az NDK és a tiszta SDK között a feladattól függ. Az Android SDK kész Java/Kotlin API-kat biztosít a forgatókönyvek 90%-ához — munka hálózattal, fájlokkal, értesítésekkel, kamerával. Az NDK akkor csatlakozik, amikor ezek az API-k nem biztosítják a szükséges teljesítményt vagy funkcionalitást. Például a valós idejű hangfeldolgozás SDK-n keresztül lehetséges, de 50–200 ms késleltetéssel, míg a natív könyvtár Oboe-n keresztül 5–15 ms-ra csökkenti a késleltetést.

APK méret — egy másik tényező. Az NDK hozzáadása növeli az alkalmazás méretét, mivel minden ABI architektúra külön .so könyvtárat igényel. Az Android App Bundle (AAB) használata azonban enyhíti a problémát: a Google Play csak a felhasználó architektúrájának megfelelő könyvtárat szállítja. Egy tipikus natív projekt 1–10 MB-ot ad hozzá a telepítési mérethez az eszközön.

SDK és NDK összehasonlítása kritériumok szerint

KrériumSDK (Kotlin/Java)NDK (C/C++)
TeljesítményKözepes (JIT/AOT fordítás)Magas (gépi kód)
Hang késleltetés50–200 ms5–15 ms Oboe-n keresztül
3D grafikaCanvas/OpenGL Kotlin API-n keresztülKözvetlen Vulkan/OpenGL
Fejlesztési komplexitásAlacsonyMagas (memóriakezelés, JNI)
Kód hordozhatóságaCsak AndroidLinux, Windows, macOS, iOS
APK méretMinimális+1–10 MB könyvtáranként

Az NDK architektúrája: eszközök és könyvtárak

Az NDK az Android SDK-tól külön telepíthető az SDK Manageren keresztül. Az NDK könyvtáron belül található a toolchain (fordítók), platformkönyvtárak, fejlécfájlok és segédprogramok. NDK Toolchain tartalmazza a Clang-ot az összes cél-ABI keresztfordításához: arm64-v8a, armeabi-v7a, x86_64 és x86. A fordító automatikusan kiválasztja a megfelelő architektúrát a CMake vagy ndk-build flag-ek alapján.

Az Android API-k natív kódhoz a sysroot/usr/include könyvtárban található fejlécfájlok által reprezentáltak. Ott találhatók az összes natív kódban elérhető API deklarációi: native_activity.h az Activity lifecycle-hoz, input.h a bemeneti eseményekhez, sensor.h az érzékelőkhöz. Ezen fejlécfájlok csatlakoztatása hozzáférést biztosít a hardveres képességekhez JNI réteg nélkül.

NDK könyvtárstruktúra

text
ndk/
  toolchains/
    llvm/prebuilt/windows-x86_64/
      bin/        // Clang, ld, llvm-profdata
      sysroot/    // Android API fejlécfájlok
  platforms/
    android-26/  // libc, libm, libdl API 26-hoz
    android-34/
  sources/
    cxx-stl/     // libc++ fejlécek
  build/
    cmake/       // CMake toolchain fájl

Natív Android API-k

Az NDK-n keresztül a következő natív API csoportok érhetők el: Native App Glue (Activity lifecycle kezelése C-ből), OpenGL ES 3.2 és Vulkan 1.3 (grafika), Oboe (alacsony késleltetésű hang), Neural Networks API (gépi tanulás az eszközön). Minden API rendelkezik fejlécfájllal és statikus/dinamikus könyvtárral az NDK összetételében.

A natív API-kkal való munkához nincs szükség JNI-re — a függvények közvetlenül a C/C++ kódból hívhatók meg. A Kotlin UI-val való interakcióhoz azonban továbbra is JNI szükséges. Ez a hibrid architektúra játékmotorokban fordul elő: grafika és fizika C++-ban (Vulkanon keresztül), menü és UI Kotlinban (Jetpack Compose-on keresztül).

JNI: hogyan hívja meg a Kotlin a C++-t

JNI (Java Native Interface) — a natív kód meghívásának szabványos mechanizmusa a Java/Kotlin virtuális gépből. A fejlesztő Kotlinban deklarál egy külső függvényt az external kulcsszóval, és csatlakoztatja a .so könyvtárat a System.loadLibrary-n keresztül. A C++ oldalon a függvény a JNI elnevezési konvencióval kerül deklarálásra, amely kódolja a csomagot és az osztály nevét.

Natív függvény deklarálása Kotlinban

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
}

// Használat kódban
val bridge = NativeBridge()
println(bridge.stringFromJNI())  // "Hello from C++"

JNI függvény implementációja C++-ban

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 konfigurálása NDK-hoz

CMake — az NDK elsődleges build rendszere, amely felváltotta az elavult ndk-build-t. A CMakeLists.txt fájl leírja a forrásfájlokat, könyvtárakat és fordítási flag-eket. Az Android Studio automatikusan meghívja a CMake-t a projekt build-elésekor, ha az externalNativeBuild konfigurálva van a build.gradle-ben. A CMake make fájlokat generál minden cél-ABI-hoz, és párhuzamosan fordítja a natív kódot.

Példa CMakeLists.txt natív könyvtárhoz

cmake
cmake_minimum_required(VERSION 3.22.1)
project("nativelib")

# Fejlécfájlok csatlakoztatása
include_directories(src/main/cpp/include)

# Natív könyvtár létrehozása
add_library(
    native-lib
    SHARED
    src/main/cpp/native-lib.cpp
    src/main/cpp/math_utils.cpp
    src/main/cpp/audio_processor.cpp
)

# Android rendszerkönyvtárak csatlakoztatása
target_link_libraries(
    native-lib
    android
    log
    OpenSLES
    # libc++ automatikusan csatlakozik
)

# Optimalizálási flag-ek
target_compile_options(native-lib PRIVATE -O3 -Wall -Wextra)

build.gradle konfigurálása NDK-hoz

groovy
android {
    defaultConfig {
        ndk {
            // Cél ABI-k a build-hez
            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 és többplatformos build

ABI (Application Binary Interface) — a gépi kód formátuma, amely meghatározza a kompatibilitást az eszköz processzorával. Minden ARM vagy x86 architektúrának saját ABI-ja van. Az NDK külön fordítja a natív kódot minden megadott ABI-hoz. A leggyakoribb ABI-k 2026-ban: arm64-v8a (a modern eszközök 99%-a), armeabi-v7a (régi 32 bites eszközök), x86_64 (emulátor és Chromebook).

Az abiFilters megadása a build.gradle-ben csak a szükséges architektúrákra korlátozza a build-et, ami csökkenti a fordítási időt. A Google Play számára ajánlott az összes olyan ABI-t belefoglalni, amelyekkel a könyvtár kompatibilis — ez garantálja a működést minden eszközön. A Google Play Console lehetővé teszi az ABI-specifikus APK szállítás konfigurálását az App Bundle-on keresztül.

Eszköz ABI meghatározása natív kódban

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");
}
ABIArchitektúraBithosszEszközök
arm64-v8aARMv8-A64 bitesSzinte minden modern telefon
armeabi-v7aARMv7-A32 bitesRégi eszközök (2020 előtt)
x86_64x86-6464 bitesEmulátor, Chromebook
x86x86 IA-3232 bitesElavult emulátorok

Natív kód példák C++-ban

Vizsgáljunk meg egy gyakorlati példát: egy matematikai könyvtár lebegőpontos számokkal való munkához. A natív kód C++-ban hatékonyabban végzi a számításokat, mint Kotlin, köszönhetően a NEON ARM utasításokhoz való közvetlen hozzáférésnek és a tömbhatárok ellenőrzésének hiányának futásidőben. Ez a példa az NDK használatának tipikus mintáját mutatja — nehéz számítások áthelyezése a natív rétegbe.

Matematikai műveletek natív kódban

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

    // Átlag és szórás számítása
    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);

    // Normalizálás: (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;
}

Naplózás natív kódból

A natív kód hibakereséséhez használja a __android_log_print makrót az android/log.h könyvtárból. Az üzenetek a Logcat-ben jelennek meg a Java/Kotlin naplók mellett. A naplózási szint (ANDROID_LOG_DEBUG, ANDROID_LOG_ERROR) segít az üzenetek szűrésében.

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++) {
        // Nehéz feldolgozás
        LOGD("Item %d processed", i);
    }

    LOGD("Processing complete");
}

Gyakran Ismételt Kérdések

Kötelező az NDK használata az Android fejlesztéshez?

Nem. A legtöbb alkalmazáshoz elegendő az SDK Kotlinban. Az NDK szükséges nagy teljesítményű feladatokhoz: valós idejű hang/videó feldolgozás, 3D grafika, kriptográfia vagy meglévő C/C++ projektek újrafelhasználása.

Milyen fordítót használ az NDK?

Az NDK a Clang-ot használja az LLVM toolchain-ből. Az NDK r23-tól kezdve a GCC teljesen eltávolításra került. A Clang keresztfordítja a kódot az összes Android ABI-hoz: arm64-v8a, armeabi-v7a, x86_64, x86.

Mi az ABI az NDK kontextusában?

ABI (Application Binary Interface) — a gépi kód formátuma, amely meghatározza a processzorral való kompatibilitást. Az NDK külön építi a .so könyvtárakat minden ABI-hoz. arm64-v8a — a fő ABI a modern Android eszközök számára.

Lehet C++ kódot hibakeresni az NDK-n keresztül?

Igen. Az Android Studio támogatja a LLDB-t — a natív kód hibakeresőjét. Lehet töréspontokat elhelyezni C++ fájlokban, megtekinteni változókat és a hívási vermet. A működéshez NDK és LLDB plugin szükséges.

Hogyan befolyásolja az NDK az APK méretét?

Minden natív könyvtár 100 KB — néhány MB-ot ad hozzá az APK-hoz. Minden ABI-hoz külön .so könyvtár szükséges. Az Android App Bundle csak a megfelelő architektúrát szállítja a felhasználónak, csökkentve a telepítési méretet.

Összegzés

  • NDK — eszközkészlet C/C++ kód keresztfordításához natív Android könyvtárakká a Clang fordítón keresztül.
  • JNI — interfész, amely összeköti a Kotlin/Java-t a natív kóddal az external kulcsszó és függvényelnevezési konvenciók segítségével.
  • CMake — az NDK elsődleges build rendszere, a CMakeLists.txt fájlon és a Gradle-ben lévő externalNativeBuild-en keresztül konfigurálható.
  • ABI meghatározza a processzor architektúráját — arm64-v8a, armeabi-v7a, x86_64. Minden ABI a könyvtár külön build-elését igényli.
  • Csak olyan feladatokhoz használja az NDK-t, amelyek magas teljesítményt igényelnek: játékok, hang, grafika, kriptográfia, gépi tanulás az eszközön.
  • A Google Play támogatja az ABI szétválasztást az App Bundle-on keresztül: a felhasználó csak az eszköze architektúrájának megfelelő könyvtárat kapja.
  • A natív könyvtárak jelentősen megnövelik az APK-t, de maximális teljesítményt és alacsony késleltetést biztosítanak a kritikus műveletekhez.

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is