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 غلط طریقے سے پکڑ سکتا ہے۔ حل: پینی لسٹنر کے ذریعے لائبریری کو سفید فہرست میں شامل کریں، لائبریری کو اس ورژن میں اپ ڈیٹ کریں جس میں پس منظر کے تھریڈ پر واضح سوئچنگ ہو، یا 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 ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں