StrictMode হল Android SDK-তে নির্মিত একটি ডেভেলপার টুল যা রিয়েল টাইমে অ্যাপ্লিকেশনের মূল থ্রেডে আকস্মিক I/O অপারেশন এবং নেটওয়ার্ক কল সনাক্ত করে এবং রিপোর্ট করে। এটি ত্রুটিগুলি ঠিক করে না বরং একটি ডিটেক্টর হিসেবে কাজ করে — কনফিগার করা নীতি লঙ্ঘন হলে ব্যতিক্রম ছোড়ে বা LogCat-এ লেখে। Google, 2024 অনুসারে, সঠিক StrictMode কনফিগারেশন অ্যাপ প্রকাশের আগে 80% পর্যন্ত পারফরম্যান্স সমস্যা সনাক্ত করতে পারে।
মূল বিষয়গুলি
StrictMode হল একটি API যা API Level 9 (Android 2.3 Gingerbread) থেকে Android SDK-তে অন্তর্ভুক্ত। এর কাজ হল রানটাইমে মূল (UI) থ্রেডে ভারী অপারেশনের আকস্মিক সম্পাদন সনাক্ত করা যা UI রেন্ডারিং ব্লক করতে পারে। মূল থ্রেড ব্যবহারকারীর ইনপুট প্রক্রিয়াকরণ, লেআউট গণনা এবং রেন্ডারিং পরিচালনা করে — 16 ms-এর বেশি যেকোনো ব্লক একটি ফ্রেম ড্রপের কারণ হয়।
StrictMode “দ্রুত ব্যর্থ হন” নীতিটি অনুসরণ করে — যত তাড়াতাড়ি সম্ভব সমস্যাটি সনাক্ত করুন, আদর্শভাবে তার প্রথম উপস্থিতির মুহুর্তে। ব্যবহারকারীদের ধীরগতির অভিযোগের জন্য অপেক্ষা করার পরিবর্তে, ডেভেলপার ডেভেলপমেন্ট পর্যায়ে সরাসরি একটি সংকেত (লগ, ডায়ালগ বা ক্র্যাশ) পায়। টুলটির অতিরিক্ত লাইব্রেরি বা Gradle কনফিগারেশনের প্রয়োজন নেই — শুধু Application.onCreate-এ কয়েক লাইন কোড, এবং এটি সমস্ত ডিভাইসে স্বয়ংক্রিয়ভাবে কাজ করে।
StrictMode সমস্ত Android ডেভেলপারের জন্য ডিজাইন করা হয়েছে, অভিজ্ঞতা নির্বিশেষে। নতুনদের জন্য, এটি ভাল অভ্যাস গঠনে সহায়তা করে (UI থ্রেডে নেটওয়ার্ক অনুরোধ না করা); অভিজ্ঞ ডেভেলপারদের জন্য, এটি CI/CD পাইপলাইনে গুণমান নিয়ন্ত্রণ স্বয়ংক্রিয় করে। বড় প্রকল্পগুলি (Google, Uber, Spotify) penaltyDeath সহ ডিবাগ বিল্ডে StrictMode অন্তর্ভুক্ত করে এবং BuildConfig.DEBUG চেকের মাধ্যমে রিলিজ বিল্ডে এটি নিষ্ক্রিয় করে।
StrictMode সিস্টেম কলগুলিকে আটকায় যা থ্রেড ব্লক করতে পারে এবং সক্রিয় নীতির সেটের সাথে তাদের তুলনা করে। যদি একটি কল কোনো নীতির সাথে মেলে এবং মূল থ্রেডে কার্যকর করা হয়, তবে StrictMode নির্দিষ্ট দণ্ড প্রয়োগ করে। আটকানোর প্রক্রিয়াটি একটি ইন-প্রসেস হুকের মাধ্যমে বাস্তবায়িত হয় — এটি রিফ্লেকশন ব্যবহার করে না এবং ন্যূনতম ওভারহেডের সাথে কাজ করে।
যখন StrictMode নীতি সক্রিয় হয়, এটি সিস্টেম কলের প্রবেশ বিন্দুতে (FileInputStream, FileOutputStream, Socket, URLConnection) তার হ্যান্ডলার ইনজেক্ট করে। যখন অ্যাপ্লিকেশন মূল থ্রেডে, উদাহরণস্বরূপ, URLConnection.openStream কল করে, StrictMode বর্তমান থ্রেড পরীক্ষা করে — যদি এটি মূল থ্রেড হয়, টুলটি সক্রিয় হয়। Android 6.0+-এ, প্রক্রিয়াটি বর্ধিত করা হয়েছে: মূল থ্রেডে নেটওয়ার্ক কল StrictMode ছাড়াও NetworkOnMainThreadException তৈরি করে, কিন্তু StrictMode ডিস্ক I/O নিয়ন্ত্রণেরও অনুমতি দেয়।
প্রতিটি নীতির নিজস্ব দণ্ড প্রকার বা সংমিশ্রণ থাকতে পারে: penaltyLog — স্ট্যাক ট্রেস সহ LogCat-এ লেখে, penaltyDialog — ব্যবহারকারীকে একটি ডায়ালগ দেখায় (শুধুমাত্র ডিবাগ), penaltyDeath — ব্যতিক্রম ছোড়ে এবং অ্যাপ ক্র্যাশ করে, penaltyDropBox — পরবর্তী বিশ্লেষণের জন্য DropBoxManager-এ ডেটা সংরক্ষণ করে। CI/CD পাইপলাইনের জন্য, penaltyDeath সুপারিশ করা হয় — এটি নিশ্চিত করে যে লঙ্ঘন সহ কোনো মার্জ অলক্ষিত না যায়।
class App : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyDeath()
.build()
)
}
}
}
StrictMode নীতিগুলিকে দুটি স্তরে বিভক্ত করে: ThreadPolicy (থ্রেড-স্তর — মূল থ্রেডে কী করা যাবে না) এবং VmPolicy (ভার্চুয়াল মেশিন — মেমরি এবং সম্পদ লিক)। উভয় স্তর স্বাধীনভাবে কনফিগার করা হয় এবং সমান্তরালে কাজ করে।
থ্রেড স্তরে, StrictMode চার ধরনের লঙ্ঘন নিয়ন্ত্রণ করে: ডিস্ক রিড (detectDiskReads), ডিস্ক রাইট (detectDiskWrites), নেটওয়ার্ক অপারেশন (detectNetwork), এবং কাস্টম স্লো কল (detectCustomSlowCalls)। disk_read মূল থ্রেডে SharedPreferences, SQLite বা ফাইল পড়ার উপর সক্রিয় হয়। network HTTP অনুরোধ, WebSocket এবং Socket সংযোগে সক্রিয় হয়। Android 11+-এ, আনবাফার্ড I/O সনাক্ত করার জন্য detectUnbufferedIO যোগ করা হয়েছিল।
VmPolicy ART ভার্চুয়াল মেশিন স্তরে লিক নিয়ন্ত্রণ করে: detectActivityLeaks (ক্রিয়াকলাপ যা ধ্বংস হয়নি), detectLeakedClosableObjects (বন্ধ না করা Cursor, Stream, Socket), detectLeakedRegistrationObjects (অনিবন্ধিত BroadcastReceiver, ServiceConnection)। যদি VmPolicy সনাক্ত করে যে একটি Activity তৈরি করা হয়েছিল কিন্তু onDestroy কল করার পর ধ্বংস হয়নি, এটি সম্পূর্ণ স্ট্যাক ট্রেস আউটপুট করে — যা মেমরি লিক ডিবাগিংয়ে ঘন্টার পর ঘন্টা বাঁচায়।
| নীতি | স্তর | কী সনাক্ত করে |
|---|---|---|
| detectDiskReads | Thread | UI থ্রেডে SharedPrefs, SQLite, ফাইল পড়া |
| detectDiskWrites | Thread | UI থ্রেডে SharedPrefs, SQLite, ফাইলে লেখা |
| detectNetwork | Thread | UI থ্রেডে যেকোনো নেটওয়ার্ক অপারেশন |
| detectActivityLeaks | VM | ক্রিয়াকলাপ যা onDestroy থেকে বেঁচে থাকে |
| detectLeakedClosableObjects | VM | বন্ধ না করা Cursor, Stream, Socket |
detectCustomSlowCalls-এর মাধ্যমে, আপনি নিজের পদ্ধতিগুলিকে “সন্দেহজনক” হিসাবে চিহ্নিত করতে পারেন এবং একটি নির্দিষ্ট সীমা অতিক্রম করলে সতর্কতা পেতে পারেন। উদাহরণস্বরূপ, যদি আপনার loadUserProfile() পদ্ধতি সাধারণত 5 ms নেয় কিন্তু কখনও কখনও 200 ms নেয় — এটি StrictMode.noteSlowCall(“loadUserProfile”)-এ মোড়ানো করুন। যদি সময়কাল সীমা (ডিফল্ট 2000 ms) অতিক্রম করে, StrictMode একটি দণ্ড তৈরি করবে। সীমাটি setSlowCallDurationThreshold-এর মাধ্যমে কনফিগার করা হয়।
মৌলিক StrictMode কনফিগারেশন 10 লাইন কোড নেয় এবং একটি কাস্টম Application ক্লাসের onCreate পদ্ধতিতে করা হয়। প্রধান নিয়ম: StrictMode শুধুমাত্র ডিবাগ বিল্ডে সক্রিয় হয় — রিলিজ বিল্ডে এটি অ্যাপকে ধীর করে এবং মিথ্যা পজিটিভ তৈরি করতে পারে।
Application-কে প্রসারিত করে এমন একটি ক্লাস তৈরি করুন, android:name অ্যাট্রিবিউটের মাধ্যমে AndroidManifest.xml-এ এটি নিবন্ধন করুন এবং StrictMode কনফিগারেশন যোগ করুন। ThreadPolicy.Builder সমস্ত ডিটেক্টর এবং সমস্ত দণ্ড প্রকার অন্তর্ভুক্ত করে (ডায়ালগ ব্যতীত — এটি শুধুমাত্র যখন ডিবাগার সংযুক্ত থাকে তখন কাজ করে)। VmPolicy.Builder Activity লিক এবং Closable অবজেক্টের জন্য ডিটেক্টর যোগ করে। বড় প্রকল্পের জন্য (100+ স্ক্রিন), Activity লিক ডিটেক্টরে penaltyDeath সহ VmPolicy কনফিগার করার সুপারিশ করা হয় — এটি কঠোর কিন্তু কার্যকর।
class App : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectActivityLeaks()
.detectLeakedClosableObjects()
.detectLeakedRegistrationObjects()
.penaltyLog()
.penaltyDeath()
.build()
)
}
}
}
CI/CD-তে স্বয়ংক্রিয় নিয়ন্ত্রণের জন্য, penaltyDeath ব্যবহার করুন — যদি কোনো পরীক্ষা নীতি লঙ্ঘন করে, অ্যাপ একটি ব্যতিক্রম সহ ক্র্যাশ করবে। Android Test Orchestrator-এর সাথে একত্রিত করুন যাতে প্রতিটি পরীক্ষা একটি পরিষ্কার প্রক্রিয়ায় চলে। UI পরীক্ষার (Espresso, Compose Test) জন্য, একটি কাস্টম TestRule লিখুন যা StrictMode লঙ্ঘন আটকায় এবং সেগুলিকে assertion ব্যর্থতায় রূপান্তর করে। উদাহরণ: @Before-এ, StrictMode সক্রিয় করুন, এবং @After-এ, পরীক্ষা করুন যে কোনো লঙ্ঘন ছিল না।
ডিফল্টরূপে, customSlowCall-এর জন্য সীমা 2000 ms, disk_read এবং disk_write-এর জন্য — কোনো সীমা নেই (যেকোনো অপারেশন সক্রিয় করে)। setSlowCallDurationThreshold এবং setSlowIoDurationThreshold-এর মাধ্যমে, আপনি মিলিসেকেন্ডে নিজস্ব মান সেট করতে পারেন। যদি আপনার অ্যাপ বৈধভাবে মূল থ্রেডে SharedPreferences পড়ে (ছোট কনফিগ), সীমা 10–20 ms-এ বাড়ান — এটি দ্রুত রিড ফিল্টার করবে যখন ধীর রিডগুলি রাখবে।
StrictMode একটি শক্তিশালী কিন্তু নাজুক টুল। ভুল কনফিগারেশন লক্ষ লক্ষ মিথ্যা পজিটিভের দিকে নিয়ে যায়, যার ফলে ডেভেলপাররা সেগুলিতে মনোযোগ দেওয়া বন্ধ করে দেয়। নীচে বড় Android টিমের অভিজ্ঞতা থেকে সংগৃহীত প্রমাণিত অভ্যাস দেওয়া হল।
এটি একটি কঠোর নিয়ম: StrictMode রিলিজ বিল্ডে কখনই সক্রিয় হওয়া উচিত নয়। BuildConfig.DEBUG ফ্ল্যাগ বা কাস্টম buildConfigField ব্যবহার করুন। রিলিজ বিল্ডে, অনেক তৃতীয়-পক্ষের লাইব্রেরি বৈধভাবে মূল থ্রেডে অপারেশন করে (SDK আরম্ভ, ক্যাশ লেখা), এবং StrictMode মিথ্যা পজিটিভ তৈরি করবে। তাছাড়া, রিলিজ বিল্ডে penaltyDialog শেষ ব্যবহারকারীকে একটি ডায়ালগ দেখাবে — যা অগ্রহণযোগ্য।
ছোট প্রকল্পের জন্য (1–10 স্ক্রিন), penaltyLog কনফিগার করুন — ম্যানুয়াল বিশ্লেষণের জন্য লগ যথেষ্ট। মাঝারি প্রকল্পের জন্য (10–50 স্ক্রিন), নেটওয়ার্ক এবং customSlowCalls-এ penaltyDeath যোগ করুন। বড় প্রকল্পের জন্য (50+ স্ক্রিন), CI/CD-তে penaltyDeath সহ নীতির সম্পূর্ণ সেট সক্রিয় করুন এবং স্থানীয় ডেভেলপমেন্টের জন্য penaltyLog। এই গ্র্যাডেশন ডেভেলপারদের মিথ্যা ক্র্যাশ দিয়ে ওভারলোড করা প্রতিরোধ করে যখন পাইপলাইনে গুণমান কঠোরভাবে নিয়ন্ত্রণ করে।
কিছু লাইব্রেরি (Firebase, Crashlytics, Adjust) বৈধভাবে পটভূমি অপারেশন করে যা StrictMode ভুলভাবে সনাক্ত করতে পারে। সমাধান: penaltyListener-এর মাধ্যমে লাইব্রেরিটিকে একটি সাদা তালিকায় যোগ করুন, লাইব্রেরিটিকে একটি সংস্করণে আপডেট করুন যা স্পষ্টভাবে পটভূমি থ্রেডে স্যুইচ করে, অথবা StrictMode.vmPolicy ব্যবহার করুন। Android 11+-এ, স্ট্যাক ট্রেস দ্বারা লঙ্ঘনের প্রোগ্রাম্যাটিক ফিল্টারিংয়ের জন্য StrictMode.OnVmViolationListener চালু করা হয়েছিল।
// penaltyListener-এর মাধ্যমে মিথ্যা পজিটিভ ফিল্টারিং
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyListener { violation ->
val stack = violation.stackTraceToString()
if ("com.google.firebase" !in stack) {
logViolation(violation)
}
}
.build()
)
StrictMode Android ইকোসিস্টেমে একমাত্র গুণমান নিয়ন্ত্রণ টুল নয়। এর স্থান বোঝার জন্য, আসুন মূল মাপকাঠিতে এটিকে Android Lint, Android Profiler এবং Perfetto-এর সাথে তুলনা করি: পরীক্ষার সময়, বিশ্লেষণের গভীরতা এবং অটোমেশন।
| মাপকাঠি | StrictMode | Android Lint | Profiler / Perfetto |
|---|---|---|---|
| পরীক্ষার সময় | রানটাইম (অ্যাপ চলাকালীন) | কম্পাইল সময় (লঞ্চের আগে) | রানটাইম (পোস্ট-মর্টেম) |
| কী পরীক্ষা করে | ডিস্ক, নেটওয়ার্ক, লিক | XML, কোড, সম্পদ | CPU, মেমরি, নেটওয়ার্ক, শক্তি |
| অটোমেশন | penaltyDeath-এর মাধ্যমে CI/CD | Gradle টাস্ক + lint-baseline | ম্যানুয়াল বিশ্লেষণ প্রয়োজন |
| গভীরতা | শুধুমাত্র UI থ্রেড এবং লিক | স্ট্যাটিক কোড বিশ্লেষণ | সম্পূর্ণ পারফরম্যান্স চিত্র |
| মিথ্যা পজিটিভ | মাঝারি (লাইব্রেরির উপর নির্ভরশীল) | কম (কনফিগার করা নিয়ম) | কোনোটি নয় (প্রকৃত পরিমাপ) |
সেরা কৌশল হল তিনটি পদ্ধতি একত্রিত করা: Android Lint কম্পাইল সময়ে স্পষ্ট ত্রুটি ধরে (যেমন, ভুলে যাওয়া IdleHandler), StrictMode রানটাইমে সমস্যা সনাক্ত করে, এবং Android Profiler / Perfetto গভীর বিশ্লেষণের জন্য ব্যবহৃত হয় যখন প্রথম দুটি টুল উত্তর দেয় না। বাস্তব প্রকল্পে (Google Maps, Instagram), StrictMode ডেভেলপমেন্টের দ্বিতীয় সপ্তাহে চালু করা হয় — মৌলিক আর্কিটেকচার সেট আপ করার পরপরই।
আসুন দুটি বাস্তব দৃশ্য দেখি যেখানে StrictMode পারফরম্যান্স সমস্যা সনাক্ত এবং ঠিক করতে সাহায্য করে: মূল থ্রেডে SharedPreferences পড়া এবং একটি অনিবন্ধিত কলব্যাকের মাধ্যমে Activity লিক।
অ্যাপ স্টার্টআপে, detectDiskReads নীতি সহ StrictMode মূল থ্রেডে SharedPreferences পড়া সনাক্ত করবে। সমাধান: CoroutineScope-এর মাধ্যমে কনফিগারেশন অ্যাসিঙ্ক্রোনাসভাবে লোড করুন বা স্টার্টআপে মেমরিতে ক্যাশ করুন। SharedPreferences ডিস্ক থেকে XML ফাইল সিঙ্ক্রোনাসভাবে পড়ে — এমনকি ছোট ফাইল (1–2 KB) হলেও, অপারেশনে 1–5 ms লাগে, এবং সস্তা ডিভাইসে 20 ms পর্যন্ত, যা ফ্রেম ড্রপের কারণ হতে পারে।
// ❌ সমস্যাযুক্ত কোড — UI থ্রেডে SharedPrefs পড়া
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// StrictMode detectDiskReads → লঙ্ঘন!
prefs = getSharedPreferences("config", MODE_PRIVATE)
}
}
// ✅ সংশোধিত কোড — Coroutine-এর মাধ্যমে পড়া
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loadConfigAsync()
}
}
VmPolicy.detectActivityLeaks সহ StrictMode এমন একটি Activity সনাক্ত করবে যা স্ট্যাক থেকে বেরিয়ে গেছে (finish কল করা হয়েছে) কিন্তু Activity অবজেক্ট একটি স্ট্যাটিক রেফারেন্স বা অনিবন্ধিত কলব্যাকের কারণে মেমরিতে রয়ে গেছে। সাধারণ দৃশ্য: onPause-এ unregister কল না করে onResume-এ EventBus বা LocationListener নিবন্ধন করা। VmPolicy একটি স্ট্যাক ট্রেস আউটপুট করবে যা নির্দেশ করে যে লাইনটি যেখানে রেফারেন্স তৈরি করা হয়েছিল।
// ❌ লিক — কলব্যাক বাতিল করা হয়নি
private var locationCallback: LocationCallback? = null
override fun onResume() {
super.onResume()
locationCallback = LocationCallback(this::onLocationUpdated)
locationManager.register(locationCallback) // StrictMode → লিক!
}
override fun onPause() {
super.onPause()
// ভুলে গেছেন: locationManager.unregister(locationCallback)
}
সচরাচর জিজ্ঞাসা
StrictMode সামান্য ওভারহেড যোগ করে — প্রতিটি সিস্টেম কল নীতির বিরুদ্ধে পরীক্ষা করা হয়। পারফরম্যান্স প্রভাব ডিবাগ বিল্ডে 1–3% এবং রিলিজে অনুপস্থিত (যেখানে StrictMode নিষ্ক্রিয়)। পুরানো ডিভাইসে (Android 6–8) detectAll সক্রিয় করলে, ওভারহেড 5% পর্যন্ত পৌঁছাতে পারে, তাই শুধুমাত্র প্রয়োজনীয় নীতিগুলি কনফিগার করার সুপারিশ করা হয়।
হ্যাঁ, StrictMode Jetpack Compose-এর সাথে সম্পূর্ণ সামঞ্জস্যপূর্ণ। ডিস্ক এবং নেটওয়ার্ক নীতিগুলি UI ফ্রেমওয়ার্ক থেকে স্বাধীন, ফ্রেমওয়ার্ক স্তরে কাজ করে। তাছাড়া, Compose-এ UI ব্লকের গুরুত্ব বেশি — Compose উচ্চ রিফ্রেশ রেট ডিভাইসে 120 FPS-এ ফ্রেম পুনরায় আঁকে, তাই ফাইল পড়তে অতিরিক্ত 5 ms বেশি লক্ষণীয় হয়ে ওঠে।
Android 8.1 (API 27) থেকে, SharedPreferences মেমরি ক্যাশিং ব্যবহার করতে পারে — যদি ফাইলটি ইতিমধ্যে পড়া হয়ে থাকে, পুনরায় পড়া StrictMode সক্রিয় করবে না। নিশ্চিত করুন যে আপনি প্রথমবার getSharedPreferences কল করছেন (কোল্ড রিড) এবং detectDiskReads নীতি সক্রিয় আছে। এছাড়াও পরীক্ষা করুন যে StrictMode একটি পিতামাতাহীন Fragment-এ ওভাররাইড করা হয়নি।
JUnit পরীক্ষায়, @Before-এ StrictMode.allowThreadDiskReads() এবং StrictMode.allowThreadDiskWrites() ব্যবহার করুন, এবং @After-এ StrictMode.enableDefaults()-এর মাধ্যমে সেটিংস পুনরুদ্ধার করুন। ইন্সট্রুমেন্টেশন পরীক্ষার জন্য, মূল নীতির অস্থায়ী সংরক্ষণ সহ একটি কাস্টম TestRunner ব্যবহার করুন। Espresso পরীক্ষায়, StrictMode-সংবেদনশীল কোড একটি IdlingResource-এ মোড়ানো সুবিধাজনক।
StrictMode শুধুমাত্র Android SDK-এর মাধ্যমে Android প্ল্যাটফর্মে কাজ করে। Kotlin Multiplatform (KMP)-এ, commonMain কোড StrictMode ব্যবহার করতে পারে না, কিন্তু androidMain-এর জন্য আপনি এটি যথারীতি যোগ করতে পারেন। iOS অংশের জন্য, একটি অ্যানালগ ব্যবহার করুন — মূল থ্রেডের জন্য DispatchQueue.main.async assertion।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন