NDK Android: คืออะไร, Native Development Kit และ JNI สำหรับ C++

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-09 เวลาอ่าน: 10 นาที

NDK (Native Development Kit) คือชุดเครื่องมือสำหรับเขียนบางส่วนของแอปพลิเคชันด้วยภาษา C และ C++ สำหรับ Android แตกต่างจาก Android SDK ทั่วไป NDK จะคอมไพล์โค้ดเป็นไลบรารีเนทีฟ (.so) ที่ทำงานโดยตรงกับโปรเซสเซอร์โดยไม่มีชั้นเครื่องเสมือน ตาม Google NDK Guides, 2026 NDK ใช้สำหรับการคำนวณประสิทธิภาพสูง เกม การประมวลผลเสียง และการนำโปรเจกต์ C/C++ ที่มีอยู่กลับมาใช้ใหม่ JNI (Java Native Interface) เชื่อมต่อโค้ดเนทีฟกับ Kotlin และ Java

ประเด็นสำคัญ

  • NDK — ชุดเครื่องมือสำหรับคอมไพล์โค้ด C/C++ เป็นไลบรารีเนทีฟสำหรับ Android
  • JNI — อินเทอร์เฟซสำหรับการโต้ตอบระหว่างเครื่องเสมือน Java/Kotlin และโค้ดเนทีฟ
  • 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 และยูทิลิตีการบิวด์ นักพัฒนาเขียนโค้ดเนทีฟด้วยภาษา C หรือ C++ คอมไพล์เป็นไฟล์ .so (ออบเจกต์ที่ใช้ร่วมกัน) และเชื่อมต่อกับแอปพลิเคชันผ่าน JNI

NDK ไม่ได้แทนที่ Android SDK แต่เสริมกัน UI วงจรชีวิต และบริการระบบทั้งหมดยังคงอยู่ใน Kotlin หรือ Java โค้ดเนทีฟแก้ไขงานเฉพาะ: การคำนวณทางคณิตศาสตร์ การเข้ารหัส โคเดก ฟิสิกส์ในเกม Google แนะนำให้ใช้ NDK เฉพาะเมื่อ SDK ไม่ให้ประสิทธิภาพหรือการเข้าถึงความสามารถของฮาร์ดแวร์ที่ต้องการ

ประวัติของ NDK เริ่มต้นในปี 2009 (NDK r1) ในช่วงเวลานี้ ชุดเครื่องมือได้พัฒนาจากชุดสคริปต์ทดลองไปสู่ระบบที่เติบโตเต็มที่พร้อมรองรับ CMake การดีบักด้วย LLDB และการโปรไฟล์ ในปี 2026 เวอร์ชันปัจจุบันคือ NDK r27 พร้อม Clang 19 รองรับ C++20 อย่างเต็มที่ และ libc++ เป็นไลบรารีมาตรฐานเพียงหนึ่งเดียว

ความสามารถหลักของ NDK

NDK มอบการเข้าถึงความสามารถระดับต่ำของ Android ให้นักพัฒนาผ่าน 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ระบบบิวด์สำหรับไลบรารีเนทีฟ
LLDBดีบักเกอร์โค้ดเนทีฟใน Android Studio
ndk-buildระบบบิวด์แบบเดิม (ถูกแทนที่โดย CMake)

NDK กับ SDK: เมื่อใดที่ต้องการโค้ดเนทีฟ

การเลือกระหว่าง NDK และ SDK บริสุทธิ์ขึ้นอยู่กับงาน Android SDK มี API Java/Kotlin พร้อมใช้สำหรับ 90% ของสถานการณ์ — เครือข่าย ไฟล์ การแจ้งเตือน กล้อง NDK ใช้เมื่อ API เหล่านี้ไม่ให้ประสิทธิภาพหรือฟังก์ชันที่ต้องการ ตัวอย่างเช่น การประมวลผลเสียงแบบเรียลไทม์ ผ่าน SDK เป็นไปได้แต่มีความหน่วง 50–200 มิลลิวินาที ในขณะที่ไลบรารีเนทีฟผ่าน Oboe ลดความหน่วงลงเหลือ 5–15 มิลลิวินาที

ขนาด APK เป็นอีกปัจจัยหนึ่ง การเพิ่ม NDK ทำให้ขนาดแอปพลิเคชันเพิ่มขึ้นเนื่องจากแต่ละสถาปัตยกรรม ABI ต้องมีไลบรารี .so แยกต่างหาก อย่างไรก็ตาม การใช้ Android App Bundle (AAB) ช่วยลดปัญหา: Google Play ส่งเฉพาะไลบรารีที่ตรงกับสถาปัตยกรรมของผู้ใช้ โปรเจกต์เนทีฟทั่วไปเพิ่ม 1–10 MB ต่อขนาดการติดตั้งต่ออุปกรณ์

การเปรียบเทียบ SDK และ NDK ตามเกณฑ์

เกณฑ์SDK (Kotlin/Java)NDK (C/C++)
ประสิทธิภาพปานกลาง (คอมไพล์ JIT/AOT)สูง (โค้ดเครื่อง)
ความหน่วงเสียง50–200 มิลลิวินาที5–15 มิลลิวินาทีผ่าน Oboe
กราฟิก 3Dผ่าน Canvas/OpenGL Kotlin APIVulkan/OpenGL โดยตรง
ความซับซ้อนในการพัฒนาต่ำสูง (การจัดการหน่วยความจำ, JNI)
การพกพาโค้ดAndroid เท่านั้นLinux, Windows, macOS, iOS
ขนาด APKน้อยที่สุด+1–10 MB ต่อไลบรารี

สถาปัตยกรรม NDK: เครื่องมือและไลบรารี

NDK ติดตั้งแยกต่างหากจาก Android SDK ผ่าน SDK Manager ภายในไดเรกทอรี NDK ประกอบด้วยชุดเครื่องมือ (คอมไพเลอร์) ไลบรารีแพลตฟอร์ม ไฟล์ส่วนหัว และยูทิลิตี ชุดเครื่องมือ NDK รวมถึง Clang สำหรับครอสคอมไพล์ไปยัง ABI เป้าหมายทั้งหมด: arm64-v8a, armeabi-v7a, x86_64 และ x86 คอมไพเลอร์จะเลือกสถาปัตยกรรมที่ต้องการโดยอัตโนมัติตามแฟล็ก CMake หรือ ndk-build

Android API สำหรับโค้ดเนทีฟมีให้โดยไฟล์ส่วนหัวในไดเรกทอรี sysroot/usr/include ที่นั่นมีการประกาศสำหรับ API ทั้งหมดที่พร้อมใช้งานในโค้ดเนทีฟ: native_activity.h สำหรับวงจรชีวิต 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

API เนทีฟของ Android

ผ่าน NDK สามารถใช้กลุ่ม API เนทีฟต่อไปนี้ได้: Native App Glue (การจัดการวงจรชีวิต Activity จาก C), OpenGL ES 3.2 และ Vulkan 1.3 (กราฟิก), Oboe (เสียงหน่วงต่ำ), Neural Networks API (การเรียนรู้ของเครื่องบนอุปกรณ์) แต่ละ API มีไฟล์ส่วนหัวและไลบรารีแบบสแตติก/ไดนามิกเป็นส่วนหนึ่งของ NDK

การทำงานกับ API เนทีฟไม่ต้องการ JNI — ฟังก์ชันถูกเรียกโดยตรงจากโค้ด C/C++ อย่างไรก็ตาม การโต้ตอบกับ UI ใน Kotlin ยังคงต้องใช้ JNI สถาปัตยกรรมไฮบริดนี้พบได้ทั่วไปในเอ็นจินเกม: กราฟิกและฟิสิกส์ใน C++ (ผ่าน Vulkan), เมนูและ UI ใน Kotlin (ผ่าน Jetpack Compose)

JNI: Kotlin เรียก C++ อย่างไร

JNI (Java Native Interface) เป็นกลไกมาตรฐานสำหรับเรียกโค้ดเนทีฟจากเครื่องเสมือน Java/Kotlin นักพัฒนาประกาศฟังก์ชันภายนอกใน Kotlin ด้วยคีย์เวิร์ด external และโหลดไลบรารี .so ผ่าน System.loadLibrary ในฝั่ง C++ ฟังก์ชันถูกประกาศโดยใช้ธรรมเนียมการตั้งชื่อ JNI ซึ่งเข้ารหัสชื่อแพ็กเกจและคลาส

การประกาศฟังก์ชันเนทีฟใน 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 สร้างเมกไฟล์สำหรับแต่ละ ABI เป้าหมายและคอมไพล์โค้ดเนทีฟแบบขนาน

ตัวอย่าง CMakeLists.txt สำหรับไลบรารีเนทีฟ

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

# รวมไฟล์ส่วนหัว
include_directories(src/main/cpp/include)

# สร้างไลบรารีเนทีฟ
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 และการบิวด์ข้ามแพลตฟอร์ม

ABI (Application Binary Interface) คือรูปแบบโค้ดเครื่องที่กำหนดความเข้ากันได้กับโปรเซสเซอร์ของอุปกรณ์ แต่ละสถาปัตยกรรม ARM หรือ x86 มี ABI ของตัวเอง NDK คอมไพล์โค้ดเนทีฟแยกต่างหากสำหรับแต่ละ ABI ที่ระบุ ABI ที่พบบ่อยที่สุดในปี 2026: arm64-v8a (99% ของอุปกรณ์สมัยใหม่), armeabi-v7a (อุปกรณ์ 32 บิตรุ่นเก่า), x86_64 (โปรแกรมจำลองและ Chromebook)

การระบุ abiFilters ใน build.gradle จำกัดการบิวด์เฉพาะสถาปัตยกรรมที่ต้องการ ลดเวลาในการคอมไพล์ สำหรับ Google Play แนะนำให้รวม ABI ทั้งหมดที่ไลบรารีรองรับ — สิ่งนี้รับประกันว่าทำงานได้บนอุปกรณ์ทั้งหมด Google Play Console อนุญาตให้กำหนดค่าการจัดส่ง APK เฉพาะ ABI ผ่าน App Bundle

การกำหนด ABI ของอุปกรณ์ในโค้ดเนทีฟ

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 บิตโปรแกรมจำลองรุ่นเก่า

ตัวอย่างโค้ดเนทีฟใน C++

ลองพิจารณาตัวอย่างที่ใช้งานได้จริง: ไลบรารีคณิตศาสตร์สำหรับทำงานกับตัวเลขทศนิยม โค้ดเนทีฟใน C++ คำนวณได้อย่างมีประสิทธิภาพมากกว่า Kotlin เนื่องจากการเข้าถึงคำสั่ง NEON ของ ARM โดยตรงและการไม่มีการตรวจสอบขอบเขตอาร์เรย์ในรันไทม์ ตัวอย่างนี้แสดงรูปแบบการใช้งาน NDK ทั่วไป — การย้ายการคำนวณหนักไปยังชั้นเนทีฟ

การดำเนินการทางคณิตศาสตร์ในโค้ดเนทีฟ

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

การบันทึกจากโค้ดเนทีฟ

สำหรับการดีบักโค้ดเนทีฟ ให้ใช้มาโคร __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 หรือไม่?

ไม่ สำหรับแอปพลิเคชันส่วนใหญ่ Kotlin SDK ก็เพียงพอ NDK จำเป็น สำหรับงานประสิทธิภาพสูง: การประมวลผลเสียง/วิดีโอแบบเรียลไทม์ กราฟิก 3D การเข้ารหัส หรือการนำโปรเจกต์ C/C++ ที่มีอยู่กลับมาใช้ใหม่

NDK ใช้คอมไพเลอร์ใด?

NDK ใช้ Clang จากชุดเครื่องมือ LLVM ตั้งแต่ NDK r23 เป็นต้นไป GCC ถูกลบออกอย่างสมบูรณ์ Clang ครอสคอมไพล์สำหรับ ABI Android ทั้งหมด: 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 — ดีบักเกอร์โค้ดเนทีฟ คุณสามารถตั้งจุดหยุดในไฟล์ C++ ดูตัวแปรและสแต็กการเรียก ต้องใช้ NDK และปลั๊กอิน LLDB

NDK ส่งผลต่อขนาด APK อย่างไร?

แต่ละไลบรารีเนทีฟเพิ่ม 100 KB ถึงหลาย MB ใน APK แต่ละ ABI ต้องมีไลบรารี .so แยกต่างหาก Android App Bundle ส่งเฉพาะสถาปัตยกรรมที่เหมาะสมให้ผู้ใช้ ลดขนาดการติดตั้ง

สรุป

  • NDK — ชุดเครื่องมือสำหรับครอสคอมไพล์โค้ด C/C++ เป็นไลบรารีเนทีฟสำหรับ Android โดยใช้คอมไพเลอร์ Clang
  • JNI — อินเทอร์เฟซที่เชื่อมต่อ Kotlin/Java กับโค้ดเนทีฟผ่านคีย์เวิร์ด external และธรรมเนียมการตั้งชื่อฟังก์ชัน
  • CMake — ระบบบิวด์หลักของ NDK กำหนดค่าผ่าน CMakeLists.txt และ externalNativeBuild ใน Gradle
  • ABI กำหนดสถาปัตยกรรมโปรเซสเซอร์ — arm64-v8a, armeabi-v7a, x86_64 แต่ละ ABI ต้องการการบิวด์ไลบรารีแยกต่างหาก
  • ใช้ NDK เฉพาะกับงานที่ต้องการประสิทธิภาพสูง: เกม เสียง กราฟิก การเข้ารหัส การเรียนรู้ของเครื่องบนอุปกรณ์
  • Google Play รองรับการแบ่ง ABI ผ่าน App Bundle: ผู้ใช้ได้รับเฉพาะไลบรารีสำหรับสถาปัตยกรรมอุปกรณ์ของตน
  • ไลบรารีเนทีฟเพิ่มขนาด APK อย่างมากแต่ให้ประสิทธิภาพสูงสุดและความหน่วงต่ำสำหรับการดำเนินการที่สำคัญ

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม