StrictMode एक डेवलपर टूल है जो Android SDK में बनाया गया है, जो रीयल टाइम में एप्लिकेशन के मेन थ्रेड पर आकस्मिक I/O संचालन और नेटवर्क कॉल का पता लगाता है और रिपोर्ट करता है। यह त्रुटियों को ठीक नहीं करता बल्कि एक डिटेक्टर के रूप में कार्य करता है — कॉन्फ़िगर की गई नीतियों के उल्लंघन पर अपवाद फेंकता है या LogCat में लिखता है। Google, 2024 के अनुसार, उचित StrictMode कॉन्फ़िगरेशन ऐप रिलीज़ होने से पहले 80% तक प्रदर्शन समस्याओं का पता लगा सकता है।
मुख्य बातें
StrictMode एक API है जो Android SDK में API Level 9 (Android 2.3 Gingerbread) से शामिल है। इसका कार्य रनटाइम पर मेन (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 अभिकथन।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें