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 (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 มอบการเข้าถึงความสามารถระดับต่ำของ 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 บริสุทธิ์ขึ้นอยู่กับงาน 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 (Kotlin/Java) | NDK (C/C++) |
|---|---|---|
| ประสิทธิภาพ | ปานกลาง (คอมไพล์ JIT/AOT) | สูง (โค้ดเครื่อง) |
| ความหน่วงเสียง | 50–200 มิลลิวินาที | 5–15 มิลลิวินาทีผ่าน Oboe |
| กราฟิก 3D | ผ่าน Canvas/OpenGL Kotlin API | Vulkan/OpenGL โดยตรง |
| ความซับซ้อนในการพัฒนา | ต่ำ | สูง (การจัดการหน่วยความจำ, JNI) |
| การพกพาโค้ด | Android เท่านั้น | Linux, Windows, macOS, iOS |
| ขนาด APK | น้อยที่สุด | +1–10 MB ต่อไลบรารี |
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/
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
ผ่าน 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 (Java Native Interface) เป็นกลไกมาตรฐานสำหรับเรียกโค้ดเนทีฟจากเครื่องเสมือน 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 สร้างเมกไฟล์สำหรับแต่ละ ABI เป้าหมายและคอมไพล์โค้ดเนทีฟแบบขนาน
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)
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 คอมไพล์โค้ดเนทีฟแยกต่างหากสำหรับแต่ละ 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
#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 บิต | โปรแกรมจำลองรุ่นเก่า |
ลองพิจารณาตัวอย่างที่ใช้งานได้จริง: ไลบรารีคณิตศาสตร์สำหรับทำงานกับตัวเลขทศนิยม โค้ดเนทีฟใน C++ คำนวณได้อย่างมีประสิทธิภาพมากกว่า Kotlin เนื่องจากการเข้าถึงคำสั่ง NEON ของ ARM โดยตรงและการไม่มีการตรวจสอบขอบเขตอาร์เรย์ในรันไทม์ ตัวอย่างนี้แสดงรูปแบบการใช้งาน NDK ทั่วไป — การย้ายการคำนวณหนักไปยังชั้นเนทีฟ
#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) ช่วยกรองข้อความ
#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");
}
คำถามที่พบบ่อย
ไม่ สำหรับแอปพลิเคชันส่วนใหญ่ Kotlin SDK ก็เพียงพอ NDK จำเป็น สำหรับงานประสิทธิภาพสูง: การประมวลผลเสียง/วิดีโอแบบเรียลไทม์ กราฟิก 3D การเข้ารหัส หรือการนำโปรเจกต์ C/C++ ที่มีอยู่กลับมาใช้ใหม่
NDK ใช้ Clang จากชุดเครื่องมือ LLVM ตั้งแต่ NDK r23 เป็นต้นไป GCC ถูกลบออกอย่างสมบูรณ์ Clang ครอสคอมไพล์สำหรับ ABI Android ทั้งหมด: arm64-v8a, armeabi-v7a, x86_64, x86
ABI (Application Binary Interface) คือรูปแบบโค้ดเครื่องที่กำหนดความเข้ากันได้กับโปรเซสเซอร์ NDK สร้างไลบรารี .so สำหรับแต่ละ ABI แยกกัน arm64-v8a คือ ABI หลักสำหรับอุปกรณ์ Android สมัยใหม่
ได้ Android Studio รองรับ LLDB — ดีบักเกอร์โค้ดเนทีฟ คุณสามารถตั้งจุดหยุดในไฟล์ C++ ดูตัวแปรและสแต็กการเรียก ต้องใช้ NDK และปลั๊กอิน LLDB
แต่ละไลบรารีเนทีฟเพิ่ม 100 KB ถึงหลาย MB ใน APK แต่ละ ABI ต้องมีไลบรารี .so แยกต่างหาก Android App Bundle ส่งเฉพาะสถาปัตยกรรมที่เหมาะสมให้ผู้ใช้ ลดขนาดการติดตั้ง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม