NDK (নেটিভ ডেভেলপমেন্ট কিট) হলো Android-এর জন্য C এবং C++-এ অ্যাপ্লিকেশনের অংশ লেখার একটি টুলকিট। সাধারণ Android SDK-এর বিপরীতে, NDK কোডকে নেটিভ লাইব্রেরিতে (.so) কম্পাইল করে যা ভার্চুয়াল মেশিন স্তর ছাড়া সরাসরি প্রসেসরের সাথে কাজ করে। Google NDK Guides, 2026 অনুযায়ী, NDK উচ্চ-ক্ষমতাসম্পন্ন কম্পিউটিং, গেম, অডিও প্রসেসিং এবং বিদ্যমান C/C++ প্রকল্প পুনঃব্যবহারের জন্য ব্যবহৃত হয়। JNI (জাভা নেটিভ ইন্টারফেস) নেটিভ কোডকে Kotlin এবং Java-এর সাথে সংযুক্ত করে।
মূল বিষয়
NDK (নেটিভ ডেভেলপমেন্ট কিট) হলো Android-এর জন্য C এবং C++ কোডকে এক্সিকিউটেবল লাইব্রেরিতে ক্রস-কম্পাইল করার টুলের একটি সেট। NDK-তে Clang কম্পাইলার, libc++ স্ট্যান্ডার্ড লাইব্রেরি, Android API হেডার ফাইল এবং বিল্ড ইউটিলিটি অন্তর্ভুক্ত। ডেভেলপার C বা C++-এ নেটিভ কোড লেখে, এটি .so ফাইলে (শেয়ার্ড অবজেক্ট) কম্পাইল করে এবং JNI-এর মাধ্যমে অ্যাপ্লিকেশনের সাথে সংযুক্ত করে।
NDK Android SDK-কে প্রতিস্থাপন করে না, বরং এটিকে পরিপূরক করে। সমস্ত UI, লাইফসাইকেল এবং সিস্টেম সার্ভিস Kotlin বা Java-তে থাকে। নেটিভ কোড নির্দিষ্ট কাজ সমাধান করে: গাণিতিক গণনা, ক্রিপ্টোগ্রাফি, কোডেক, গেমে ফিজিক্স। Google সুপারিশ করে শুধুমাত্র তখনই NDK ব্যবহার করার জন্য যখন SDK প্রয়োজনীয় কর্মক্ষমতা বা হার্ডওয়্যার ক্ষমতায় অ্যাক্সেস প্রদান করে না।
NDK-র ইতিহাস ২০০৯ (NDK r1) থেকে শুরু হয়। এই সময়ে, টুলকিট পরীক্ষামূলক স্ক্রিপ্টের সেট থেকে CMake, LLDB ডিবাগিং এবং প্রোফাইলিং সমর্থন সহ একটি পরিপক্ক সিস্টেমে বিবর্তিত হয়েছে। ২০২৬ পর্যন্ত, বর্তমান সংস্করণ হল NDK r27 যাতে Clang 19, C++20-এর পূর্ণ সমর্থন এবং libc++ একমাত্র স্ট্যান্ডার্ড লাইব্রেরি হিসেবে রয়েছে।
NDK ডেভেলপারকে নেটিভ API-এর মাধ্যমে Android-এর নিম্ন-স্তরের ক্ষমতায় অ্যাক্সেস দেয়। প্রধান ব্যবহারের ক্ষেত্রগুলির মধ্যে অন্তর্ভুক্ত: 3D গ্রাফিক্সের জন্য OpenGL ES এবং Vulkan-এর সাথে কাজ, Oboe-এর মাধ্যমে অডিও প্রসেসিং, BoringSSL-এর মাধ্যমে ক্রিপ্টোগ্রাফিক অপারেশন এবং ARM-এর জন্য NEON অপ্টিমাইজেশন। এই সমস্ত API C/C++ থেকে উপলব্ধ এবং কম্পাইলেশনের জন্য NDK প্রয়োজন।
উপরন্তু, NDK বিদ্যমান C/C++ লাইব্রেরি Kotlin-এ পুনর্লিখন ছাড়াই পুনঃব্যবহারের অনুমতি দেয়। এটি বিশেষ করে C++-এ দীর্ঘ ইতিহাসযুক্ত প্রকল্পগুলির জন্য প্রাসঙ্গিক — গেম ইঞ্জিন (Unity, Unreal Engine), কম্পিউটার ভিশন লাইব্রেরি (OpenCV) বা ক্রিপ্টোগ্রাফিক প্যাকেজ (OpenSSL)। এই ক্ষেত্রে, NDK বছরের পর বছর উন্নয়ন সাশ্রয় করে।
| উপাদান | উদ্দেশ্য |
|---|---|
| Clang | C++20 সমর্থন সহ C/C++ কম্পাইলার |
| libc++ | স্ট্যান্ডার্ড C++ লাইব্রেরি (NDK r27-এ একমাত্র) |
| CMake | নেটিভ লাইব্রেরির জন্য বিল্ড সিস্টেম |
| LLDB | Android Studio-তে নেটিভ কোড ডিবাগার |
| ndk-build | লিগ্যাসি বিল্ড সিস্টেম (CMake দ্বারা প্রতিস্থাপিত) |
NDK এবং বিশুদ্ধ SDK-এর মধ্যে পছন্দ কাজের উপর নির্ভর করে। Android SDK 90% পরিস্থিতির জন্য প্রস্তুত Java/Kotlin API সরবরাহ করে — নেটওয়ার্কিং, ফাইল, নোটিফিকেশন, ক্যামেরা। NDK ব্যবহার করা হয় যখন এই APIগুলি প্রয়োজনীয় কর্মক্ষমতা বা কার্যকারিতা প্রদান করে না। উদাহরণস্বরূপ, SDK-এর মাধ্যমে রিয়েল-টাইম অডিও প্রসেসিং সম্ভব কিন্তু 50–200 ms লেটেন্সি সহ, যেখানে Oboe-এর মাধ্যমে নেটিভ লাইব্রেরি লেটেন্সি 5–15 ms-এ কমিয়ে আনে।
APK আকার আরেকটি কারণ। NDK যোগ করলে অ্যাপ্লিকেশনের আকার বাড়ে কারণ প্রতিটি ABI আর্কিটেকচারের জন্য আলাদা .so লাইব্রেরি প্রয়োজন। তবে, Android App Bundle (AAB) ব্যবহার সমস্যা হ্রাস করে: Google Play ব্যবহারকারীকে শুধুমাত্র তার আর্কিটেকচারের জন্য লাইব্রেরি সরবরাহ করে। একটি সাধারণ নেটিভ প্রকল্প প্রতি ডিভাইসে ইনস্টল আকারে 1–10 MB যোগ করে।
| মানদণ্ড | SDK (Kotlin/Java) | NDK (C/C++) |
|---|---|---|
| কর্মক্ষমতা | মধ্যম (JIT/AOT কম্পাইলেশন) | উচ্চ (মেশিন কোড) |
| অডিও লেটেন্সি | 50–200 ms | Oboe-এর মাধ্যমে 5–15 ms |
| 3D গ্রাফিক্স | Canvas/OpenGL Kotlin API-এর মাধ্যমে | Vulkan/OpenGL সরাসরি |
| উন্নয়ন জটিলতা | নিম্ন | উচ্চ (মেমরি ব্যবস্থাপনা, JNI) |
| কোড পোর্টেবিলিটি | শুধুমাত্র Android | Linux, Windows, macOS, iOS |
| APK আকার | সর্বনিম্ন | +1–10 MB প্রতি লাইব্রেরি |
NDK SDK Manager-এর মাধ্যমে Android SDK থেকে আলাদাভাবে ইনস্টল করা হয়। NDK ডিরেক্টরির ভিতরে টুলচেন (কম্পাইলার), প্ল্যাটফর্ম লাইব্রেরি, হেডার ফাইল এবং ইউটিলিটি থাকে। NDK টুলচেন-এ সমস্ত টার্গেট ABI: arm64-v8a, armeabi-v7a, x86_64 এবং x86-এর জন্য ক্রস-কম্পাইলেশনের জন্য Clang অন্তর্ভুক্ত। কম্পাইলার 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/ // API 26-এর জন্য libc, libm, libdl
android-34/
sources/
cxx-stl/ // libc++ হেডার
build/
cmake/ // CMake টুলচেন ফাইল
NDK-এর মাধ্যমে নিম্নলিখিত নেটিভ API গ্রুপগুলি উপলব্ধ: Native App Glue (C থেকে Activity লাইফসাইকেল ব্যবস্থাপনা), OpenGL ES 3.2 এবং Vulkan 1.3 (গ্রাফিক্স), Oboe (নিম্ন-লেটেন্সি অডিও), Neural Networks API (ডিভাইসে মেশিন লার্নিং)। প্রতিটি API-র NDK-এর অংশ হিসেবে একটি হেডার ফাইল এবং স্ট্যাটিক/ডায়নামিক লাইব্রেরি আছে।
নেটিভ API-র সাথে কাজ করতে JNI-র প্রয়োজন নেই — ফাংশনগুলি সরাসরি C/C++ কোড থেকে কল করা হয়। তবে, Kotlin-এ UI-র সাথে মিথস্ক্রিয়ার জন্য এখনও JNI প্রয়োজন। এই হাইব্রিড আর্কিটেকচার গেম ইঞ্জিনে সাধারণ: C++-এ গ্রাফিক্স এবং ফিজিক্স (Vulkan-এর মাধ্যমে), Kotlin-এ মেনু এবং UI (Jetpack Compose-এর মাধ্যমে)।
JNI (জাভা নেটিভ ইন্টারফেস) জাভা/Kotlin ভার্চুয়াল মেশিন থেকে নেটিভ কোড কল করার একটি মানক প্রক্রিয়া। ডেভেলপার Kotlin-এ external কীওয়ার্ড দিয়ে একটি বাহ্যিক ফাংশন ঘোষণা করে এবং System.loadLibrary-এর মাধ্যমে .so লাইব্রেরি লোড করে। 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 কল করে যদি build.gradle-এ externalNativeBuild কনফিগার করা থাকে। 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 (অ্যাপ্লিকেশন বাইনারি ইন্টারফেস) হলো মেশিন কোডের ফরম্যাট যা ডিভাইসের প্রসেসরের সাথে সামঞ্জস্য নির্ধারণ করে। প্রতিটি ARM বা x86 আর্কিটেকচারের নিজস্ব ABI আছে। NDK প্রতিটি নির্দিষ্ট ABI-র জন্য আলাদাভাবে নেটিভ কোড কম্পাইল করে। 2026 পর্যন্ত সবচেয়ে সাধারণ ABI: arm64-v8a (আধুনিক ডিভাইসের 99%), armeabi-v7a (পুরনো 32-বিট ডিভাইস), x86_64 (এমুলেটর এবং Chromebook)।
build.gradle-এ abiFilters উল্লেখ করলে বিল্ড শুধুমাত্র প্রয়োজনীয় আর্কিটেকচারে সীমাবদ্ধ থাকে, যা কম্পাইলেশন সময় কমায়। Google Play-র জন্য, লাইব্রেরি সমর্থিত সমস্ত ABI অন্তর্ভুক্ত করার সুপারিশ করা হয় — এটি সমস্ত ডিভাইসে কাজ করার নিশ্চয়তা দেয়। Google Play Console App Bundle-এর মাধ্যমে ABI-নির্দিষ্ট APK বিতরণ কনফিগার করার অনুমতি দেয়।
#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++-এ নেটিভ কোড ARM NEON নির্দেশাবলীতে সরাসরি অ্যাক্সেস এবং রানটাইমে অ্যারে বাউন্ডস চেকের অনুপস্থিতির কারণে Kotlin-এর চেয়ে বেশি দক্ষতার সাথে গণনা সম্পাদন করে। এই উদাহরণটি 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.h লাইব্রেরি থেকে __android_log_print ম্যাক্রো ব্যবহার করুন। Java/Kotlin লগের পাশাপাশি Logcat-এ বার্তাগুলি উপস্থিত হয়। লগিং লেভেল (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 LLVM টুলচেন থেকে Clang ব্যবহার করে। NDK r23 থেকে, GCC সম্পূর্ণরূপে সরানো হয়েছে। Clang সমস্ত Android ABI: arm64-v8a, armeabi-v7a, x86_64, x86-এর জন্য ক্রস-কম্পাইল করে।
ABI (অ্যাপ্লিকেশন বাইনারি ইন্টারফেস) হলো মেশিন কোডের ফরম্যাট যা প্রসেসরের সাথে সামঞ্জস্য নির্ধারণ করে। NDK প্রতিটি ABI-র জন্য আলাদাভাবে .so লাইব্রেরি বিল্ড করে। arm64-v8a আধুনিক Android ডিভাইসের জন্য প্রাথমিক ABI।
হ্যাঁ। Android Studio LLDB সমর্থন করে — একটি নেটিভ কোড ডিবাগার। আপনি C++ ফাইলে ব্রেকপয়েন্ট সেট করতে, ভেরিয়েবল এবং কল স্ট্যাক দেখতে পারেন। এর জন্য NDK এবং LLDB প্লাগইন প্রয়োজন।
প্রতিটি নেটিভ লাইব্রেরি APK-তে 100 KB থেকে কয়েক MB যোগ করে। প্রতিটি ABI-র জন্য আলাদা .so লাইব্রেরি প্রয়োজন। Android App Bundle ব্যবহারকারীকে শুধুমাত্র উপযুক্ত আর্কিটেকচার সরবরাহ করে, ইনস্টল আকার হ্রাস করে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন