NDK Android: Nedir, Native Development Kit ve C++ için JNI

Yazar: IT Sectr Yayınlanma: 2026-02-09 Okuma süresi: 10 dk

NDK (Native Development Kit), Android için uygulamanın bölümlerini C ve C++ ile yazmaya yarayan bir araç takımıdır. Normal Android SDK'nın aksine, NDK kodu yerel kütüphanelere (.so) derleyerek sanal makine katmanı olmadan doğrudan işlemciyle çalışır. Google NDK Kılavuzları, 2026'ya göre NDK, yüksek performanslı hesaplama, oyunlar, ses işleme ve mevcut C/C++ projelerinin yeniden kullanımı için kullanılır. JNI (Java Yerel Arayüzü) yerel kodu Kotlin ve Java ile birleştirir.

Önemli Noktalar

  • NDK — C/C++ kodunu Android için yerel kütüphanelere derleyen bir araç takımı.
  • JNI — Java/Kotlin sanal makinesi ile yerel kod arasındaki etkileşim arayüzü.
  • CMake — NDK projeleri için ana derleme sistemi, CMakeLists.txt ile yapılandırılır.
  • ABI — Kütüphanenin derlendiği hedef işlemci mimarisi (arm64-v8a, armeabi-v7a, x86_64).
  • NDK çoğu Android uygulaması için gerekli değildir ve yalnızca yüksek performans gerektiren görevlerde kullanılır.

NDK Nedir

NDK (Native Development Kit), C ve C++ kodunu Android için yürütülebilir kütüphanelere çapraz derlemek için bir araç setidir. NDK, Clang derleyicisini, libc++ standart kütüphanesini, Android API başlık dosyalarını ve derleme yardımcı programlarını içerir. Geliştirici, C veya C++ ile yerel kod yazar, bunu .so dosyalarına (paylaşılan nesneler) derler ve JNI aracılığıyla uygulamaya bağlar.

NDK, Android SDK'nın yerini almaz, onu tamamlar. Tüm kullanıcı arayüzü, yaşam döngüsü ve sistem hizmetleri Kotlin veya Java'da kalır. Yerel kod belirli görevleri çözer: matematiksel hesaplamalar, kriptografi, codec'ler, oyunlarda fizik. Google, SDK'nın gerekli performansı veya donanım yeteneklerine erişimi sağlamadığı durumlarda NDK kullanılmasını önerir.

NDK'nin tarihi 2009'a (NDK r1) dayanır. Bu süre zarfında araç takımı, deneysel bir betik koleksiyonundan CMake, LLDB hata ayıklama ve profil oluşturma desteğine sahip olgun bir sisteme dönüştü. 2026 itibarıyla güncel sürüm, Clang 19, tam C++20 desteği ve tek standart kütüphane olarak libc++ ile NDK r27'dir.

NDK'nin Temel Yetenekleri

NDK, geliştiriciye yerel API'ler aracılığıyla Android'in düşük seviyeli yeteneklerine erişim sağlar. Ana kullanım durumları şunları içerir: 3D grafikler için OpenGL ES ve Vulkan ile çalışma, Oboe ile ses işleme, BoringSSL ile kriptografik işlemler ve ARM için NEON optimizasyonları. Tüm bu API'ler C/C++'tan kullanılabilir ve derleme için NDK gerektirir.

Ayrıca NDK, mevcut C/C++ kütüphanelerinin Kotlin'de yeniden yazılmadan yeniden kullanılmasına olanak tanır. Bu, özellikle C++'da uzun geçmişi olan projeler için önemlidir — oyun motorları (Unity, Unreal Engine), bilgisayarlı görü kütüphaneleri (OpenCV) veya kriptografik paketler (OpenSSL). Bu gibi durumlarda NDK, yıllarca sürecek geliştirmeyi önler.

BileşenAmaç
ClangC++20 desteğiyle C/C++ derleyicisi
libc++Standart C++ kütüphanesi (NDK r27'de tek)
CMakeYerel kütüphaneler için derleme sistemi
LLDBAndroid Studio'da yerel kod hata ayıklayıcısı
ndk-buildEski derleme sistemi (CMake ile değiştirildi)

NDK vs SDK: Yerel Kod Ne Zaman Gerekir

NDK ve saf SDK arasındaki seçim göreve bağlıdır. Android SDK, senaryoların %90'ı için hazır Java/Kotlin API'leri sağlar — ağ, dosyalar, bildirimler, kamera. NDK, bu API'ler gerekli performansı veya işlevselliği sağlamadığında kullanılır. Örneğin, SDK aracılığıyla gerçek zamanlı ses işleme mümkündür ancak 50–200 ms gecikmeyle, Oboe aracılığıyla yerel bir kütüphane gecikmeyi 5–15 ms'ye düşürür.

APK boyutu başka bir faktördür. NDK eklemek, her ABI mimarisi ayrı bir .so kütüphanesi gerektirdiğinden uygulama boyutunu artırır. Ancak, Android App Bundle (AAB) kullanımı sorunu hafifletir: Google Play, kullanıcıya yalnızca kendi mimarisi için kütüphaneyi iletir. Tipik bir yerel proje, cihaz başına kurulum boyutuna 1–10 MB ekler.

SDK ve NDK Karşılaştırması

KriterSDK (Kotlin/Java)NDK (C/C++)
PerformansOrta (JIT/AOT derleme)Yüksek (makine kodu)
Ses gecikmesi50–200 msOboe ile 5–15 ms
3D grafiklerCanvas/OpenGL Kotlin API ileVulkan/OpenGL doğrudan
Geliştirme karmaşıklığıDüşükYüksek (bellek yönetimi, JNI)
Kod taşınabilirliğiSadece AndroidLinux, Windows, macOS, iOS
APK boyutuMinimum+1–10 MB/kütüphane

NDK Mimarisi: Araçlar ve Kütüphaneler

NDK, SDK Manager aracılığıyla Android SDK'dan ayrı olarak kurulur. NDK dizini içinde araç zinciri (derleyiciler), platform kütüphaneleri, başlık dosyaları ve yardımcı programlar bulunur. NDK Araç Zinciri, tüm hedef ABI'ler (arm64-v8a, armeabi-v7a, x86_64 ve x86) için çapraz derleme yapan Clang'ı içerir. Derleyici, CMake veya ndk-build bayraklarına göre gerekli mimariyi otomatik olarak seçer.

Yerel kod için Android API'leri, sysroot/usr/include dizinindeki başlık dosyaları tarafından sağlanır. Burada yerel kodda bulunan tüm API'lerin bildirimleri bulunur: Activity yaşam döngüsü için native_activity.h, giriş olayları için input.h, sensörler için sensor.h. Bu başlıkları dahil etmek, JNI katmanı olmadan donanım yeteneklerine erişim sağlar.

NDK Dizin Yapısı

text
ndk/
  toolchains/
    llvm/prebuilt/windows-x86_64/
      bin/        // Clang, ld, llvm-profdata
      sysroot/    // Android API başlık dosyaları
  platforms/
    android-26/  // API 26 için libc, libm, libdl
    android-34/
  sources/
    cxx-stl/     // libc++ başlıkları
  build/
    cmake/       // CMake araç zinciri dosyası

Yerel Android API'leri

NDK aracılığıyla aşağıdaki yerel API grupları kullanılabilir: Native App Glue (C'den Activity yaşam döngüsü yönetimi), OpenGL ES 3.2 ve Vulkan 1.3 (grafikler), Oboe (düşük gecikmeli ses), Neural Networks API (cihaz üzerinde makine öğrenimi). Her API'nin NDK'nin parçası olarak bir başlık dosyası ve statik/dinamik kütüphanesi vardır.

Yerel API'lerle çalışmak JNI gerektirmez — işlevler doğrudan C/C++ kodundan çağrılır. Ancak, Kotlin kullanıcı arayüzü ile etkileşim hâlâ JNI gerektirir. Bu hibrit mimari, oyun motorlarında yaygındır: C++ ile grafik ve fizik (Vulkan aracılığıyla), Kotlin ile menüler ve kullanıcı arayüzü (Jetpack Compose aracılığıyla).

JNI: Kotlin C++'ı Nasıl Çağırır

JNI (Java Yerel Arayüzü), Java/Kotlin sanal makinesinden yerel kodu çağırmak için standart bir mekanizmadır. Geliştirici, Kotlin'de external anahtar sözcüğüyle bir dış işlev bildirir ve System.loadLibrary aracılığıyla .so kütüphanesini yükler. C++ tarafında, işlev, paketi ve sınıf adını kodlayan JNI adlandırma kuralı kullanılarak bildirilir.

Kotlin'de Yerel İşlev Bildirimi

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
}

// Kodda kullanım
val bridge = NativeBridge()
println(bridge.stringFromJNI())  // "Hello from C++"

C++'ta JNI İşlev Uygulaması

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

NDK için CMakeLists.txt Ayarları

CMake, eski ndk-build'in yerini alan NDK için birincil derleme sistemidir. CMakeLists.txt dosyası kaynak dosyaları, kütüphaneleri ve derleme bayraklarını tanımlar. Android Studio, build.gradle'da externalNativeBuild yapılandırılmışsa, projeyi derlerken otomatik olarak CMake'i çağırır. CMake, her hedef ABI için makefile'lar oluşturur ve yerel kodu paralel olarak derler.

Yerel Kütüphane için CMakeLists.txt Örneği

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

# Başlık dosyalarını dahil et
include_directories(src/main/cpp/include)

# Yerel kütüphane oluştur
add_library(
    native-lib
    SHARED
    src/main/cpp/native-lib.cpp
    src/main/cpp/math_utils.cpp
    src/main/cpp/audio_processor.cpp
)

# Android sistem kütüphanelerini bağla
target_link_libraries(
    native-lib
    android
    log
    OpenSLES
    # libc++ otomatik olarak bağlanır
)

# Optimizasyon bayrakları
target_compile_options(native-lib PRIVATE -O3 -Wall -Wextra)

NDK için build.gradle Yapılandırması

groovy
android {
    defaultConfig {
        ndk {
            // Derleme için hedef ABI'ler
            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 ve Çok Platformlu Derleme

ABI (Uygulama İkili Arayüzü), cihazın işlemcisiyle uyumluluğu belirleyen makine kodu formatıdır. Her ARM veya x86 mimarisinin kendi ABI'si vardır. NDK, yerel kodu belirtilen her ABI için ayrı ayrı derler. 2026 itibarıyla en yaygın ABI'ler: arm64-v8a (modern cihazların %99'u), armeabi-v7a (eski 32-bit cihazlar), x86_64 (emülatör ve Chromebook).

build.gradle'da abiFilters belirtmek, derlemeyi yalnızca gerekli mimarilerle sınırlayarak derleme süresini kısaltır. Google Play için kütüphanenin desteklediği tüm ABI'lerin dahil edilmesi önerilir — bu, tüm cihazlarda çalışmasını garanti eder. Google Play Console, App Bundle aracılığıyla ABI'ye özel APK dağıtımını yapılandırmaya olanak tanır.

Yerel Kodda Cihaz ABI'sini Belirleme

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");
}
ABIMimariBitCihazlar
arm64-v8aARMv8-A64-bitNeredeyse tüm modern telefonlar
armeabi-v7aARMv7-A32-bitEski cihazlar (2020 öncesi)
x86_64x86-6464-bitEmülatör, Chromebook
x86x86 IA-3232-bitEski emülatörler

C++ ile Yerel Kod Örnekleri

Pratik bir örnek ele alalım: kayan noktalı sayılarla çalışmak için bir matematik kütüphanesi. C++'taki yerel kod, ARM NEON talimatlarına doğrudan erişim ve çalışma zamanında dizi sınır kontrollerinin olmaması sayesinde Kotlin'den daha verimli hesaplama yapar. Bu örnek, NDK'nin tipik bir kullanım modelini gösterir — ağır hesaplamaları yerel katmana taşıma.

Yerel Kodda Matematiksel İşlemler

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

    // Ortalama ve standart sapmayı hesapla
    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);

    // Normalleştirme: (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;
}

Yerel Koddan Günlükleme

Yerel kodda hata ayıklamak için android/log.h kütüphanesindeki __android_log_print makrosunu kullanın. Mesajlar, Java/Kotlin günlüklerinin yanında Logcat'te görünür. Günlük düzeyi (ANDROID_LOG_DEBUG, ANDROID_LOG_ERROR) mesajları filtrelemeye yardımcı olur.

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++) {
        // Ağır işleme
        LOGD("Item %d processed", i);
    }

    LOGD("Processing complete");
}

Sıkça Sorulan Sorular

Android geliştirme için NDK kullanmak zorunlu mu?

Hayır. Çoğu uygulama için Kotlin SDK yeterlidir. NDK gereklidir yüksek performanslı görevler için: gerçek zamanlı ses/video işleme, 3D grafikler, kriptografi veya mevcut C/C++ projelerinin yeniden kullanımı.

NDK hangi derleyiciyi kullanır?

NDK, LLVM araç zincirinden Clang kullanır. NDK r23'ten itibaren GCC tamamen kaldırılmıştır. Clang, tüm Android ABI'leri (arm64-v8a, armeabi-v7a, x86_64, x86) için çapraz derleme yapar.

NDK bağlamında ABI nedir?

ABI (Uygulama İkili Arayüzü), işlemciyle uyumluluğu belirleyen makine kodu formatıdır. NDK, her ABI için ayrı ayrı .so kütüphaneleri oluşturur. arm64-v8a modern Android cihazlar için birincil ABI'dir.

NDK aracılığıyla C++ kodu hata ayıklanabilir mi?

Evet. Android Studio, LLDB'yi (bir yerel kod hata ayıklayıcısı) destekler. C++ dosyalarında kesme noktaları belirleyebilir, değişkenleri ve çağrı yığınını görebilirsiniz. NDK ve LLDB eklentisi gereklidir.

NDK, APK boyutunu nasıl etkiler?

Her yerel kütüphane APK'ye 100 KB ile birkaç MB arasında ekler. Her ABI ayrı bir .so kütüphanesi gerektirir. Android App Bundle, kullanıcıya yalnızca uygun mimariyi ileterek kurulum boyutunu azaltır.

Özet

  • NDK — Clang derleyicisini kullanarak C/C++ kodunu Android için yerel kütüphanelere çapraz derleyen araç seti.
  • JNI — external anahtar sözcüğü ve işlev adlandırma kurallarıyla Kotlin/Java'yı yerel koda bağlayan arayüz.
  • CMake — NDK'nin birincil derleme sistemi, CMakeLists.txt ve Gradle'da externalNativeBuild ile yapılandırılır.
  • ABI işlemci mimarisini tanımlar — arm64-v8a, armeabi-v7a, x86_64. Her ABI ayrı bir kütüphane derlemesi gerektirir.
  • NDK'yi yalnızca yüksek performans gerektiren görevler için kullanın: oyunlar, ses, grafikler, kriptografi, cihaz üzerinde makine öğrenimi.
  • Google Play, App Bundle aracılığıyla ABI bölmeyi destekler: kullanıcı yalnızca kendi cihaz mimarisi için kütüphaneyi alır.
  • Yerel kütüphaneler APK boyutunu önemli ölçüde artırır ancak kritik işlemler için maksimum performans ve düşük gecikme sağlar.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun