StrictMode Android SDK-də quraşdırılmış tərtibatçı alətidir və real vaxt rejimində təsadüfi giriş-çıxış əməliyyatlarını və əsas tətbiq axınındakı řəbəkə çağırışlarını aşkarlayıb bildirir. Səhvləri düzəltmir, ancaq detektor rolunu oynayır — verilmiş siyasətlər pozulduqda istisnalar atır və ya LogCat-ə yazır. Google, 2024 məlumatına görə, StrictMode-un düzgün konfiqurasiyası tətbiqin buraxılışından əvvəl performans problemlərinin 80%-ə qədərini aşkarlamağa imkan verir.
Əsas Məqamlarlar
StrictMode API Level 9-dan (Android 2.3 Gingerbread) Android SDK-ya daxil olan bir API-dir. Onun vəzifəsi interfeysin render edilməsini bloklaya biləcək ağır əməliyyatların əsas (UI) axınında təsadüfi icrasını real vaxtda aşkarlamaqdır. Əsas axın istifadəçi girişinin emalı, layout hesablanması və render üçün cavabdehdir — 16 ms-dən uzun hər hansı bloklama çərçivənin buraxılmasına səbəb olur.
StrictMode “fail fast” prinsipi ilə işləyir — problemi mümkün qədər tez, tercihen ilk görünündə aşkarla. İstifadəçilərin yavaşlama şikayətlərini gözləmək əvəzinə, tərtibatçı inkişaf mərhələsində siqnal (loglar, dialoq və ya crash) alır. Alət əlavə kitabxanalar və ya Gradle konfiqurasiyası tələb etmir — Application.onCreate-də bir neçə sətr kod kifayətdir və o, bütün cihazlarda avtomatik işləyir.
StrictMode təcrübəsindən asılı olmayaraq bütün Android tərtibatçıları üçün nəzərdə tutulmuşdur. Yeni başlayanlara düzgün vərdişlər formalaşdırmağa kömək edir (UI axınında řəbəkə sorğuları etməmək), təcrübəlilərə — CI/CD pipeline-da keyfiyyətə nəzarəti avtomatlaşdırmağa. Böyük layihələr (Google, Uber, Spotify) StrictMode-u penaltyDeath ilə debug build-lərdə aktiv edir, release build-lərdə isə BuildConfig.DEBUG yoxlaması ilə söndürür.
StrictMode axını bloklaya biləcək sistem çağırışlarını tətbiq edir və onları aktiv siyasətlər dəsti ilə müqayisə edir. Əgər çağırış siyasətə uyğun gəlirsə və əsas axında icra olunursa, StrictMode təyin edilmiş penalty tətbiq edir. Tətbiq mexanizmi prosesdaxili hook vasitəsilə həyata keçirilir — reflection istifadə etmir və minimal yüklə işləyir.
Siyasət aktivləşdirildikdə StrictMode öz handlerini sistem çağırışlarının giriş nöqtəsinə (FileInputStream, FileOutputStream, Socket, URLConnection) yerləşdirir. Tətbiq, məsələn, əsas axında URLConnection.openStream çağırdıqda, StrictMode cari axını yoxlayır — əgər main thread-dədirsə, alət işə düşür. Android 6.0+-da mexanizm gücləndirilib: main thread-də řəbəkə çağırışları StrictMode olmadan belə NetworkOnMainThreadException yaradır, lakin StrictMode disk I/O-nu da idarə etməyə imkan verir.
Hər bir siyasətin öz penalty növü və ya kombinasiyası ola bilər: penaltyLog — stacktrace ilə LogCat-ə yazılır, penaltyDialog — istifadəçiyə dialoq göstərilir (yalnız debug), penaltyDeath — istisnanın atılması və tətbiqin crash-i, penaltyDropBox — məlumatların sonrakı analiz üçün DropBoxManager-də saxlanması. CI/CD pipeline üçün penaltyDeath tövsiyə olunur — bu, pozuntu ilə heç bir merge-in diqqətdən yayınmamasını təmin edir.
class App : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyDeath()
.build()
)
}
}
}
StrictMode siyasətləri iki səviyyəyə ayırır: ThreadPolicy (axın — əsas axında nə etməməli) və VmPolicy (virtual maşın — yaddaş və resurs sızıntıları). Hər iki səviyyə müstəqil konfiqurasiya olunur və paralel işləyir.
Axın səviyyəsində StrictMode dörd növ pozuntuya nəzarət edir: diskdən oxuma (detectDiskReads), diskə yazma (detectDiskWrites), řəbəkə əməliyyatları (detectNetwork) və fərdi yavaş çağırışlar (detectCustomSlowCalls). disk_read əsas axında SharedPreferences, SQLite, faylların istənilən oxunmasında işə düşür. network — HTTP sorğuları, WebSocket, Socket bağlantılarında. Android 11+-da buferlənməmiş giriş-çıxışı aşkarlamaq üçün detectUnbufferedIO əlavə edilib.
VmPolicy ART virtual maşını səviyyəsində sızıntılara nəzarət edir: detectActivityLeaks (məhv edilməmiş Activity-lər), detectLeakedClosableObjects (bağlanmamış Cursor, Stream, Socket), detectLeakedRegistrationObjects (ləğv edilməmiş BroadcastReceiver, ServiceConnection). Əgər VmPolicy Activity-nin yaradıldığını, lakin onDestroy çağırışından sonra məhv edilmədiyini aşkar edərsə, tam stack trace çap edir — bu, yaddaş sızıntılarının aradan qaldırılması saatlarına qənaət edir.
| Siyasət | Səviyyə | Aşkarladığı şey |
|---|---|---|
| detectDiskReads | Thread | UI axınında SharedPrefs, SQLite, faylların oxunması |
| detectDiskWrites | Thread | UI axınında SharedPrefs, SQLite, fayllara yazma |
| detectNetwork | Thread | UI axınında istənilən řəbəkə əməliyyatları |
| detectActivityLeaks | VM | onDestroy-dən sağ çıxmış Activity-lər |
| detectLeakedClosableObjects | VM | Bağlanmamış Cursor, Stream, Socket |
detectCustomSlowCalls vasitəsilə öz metodlarınızı “şübhəli” olaraq qeyd edə və müəyyən edilmiş hədd aşıldıqda xəbərdarlıq ala bilərsiniz. Məsələn, loadUserProfile() metodu adətən 5 ms çəkirsə, lakin bəzi hallarda 200 ms çəkirsə — onu StrictMode.noteSlowCall("loadUserProfile") ilə əhatə edin. Müddət həddi aşarsa (standart 2000 ms), StrictMode penalty yaradır. Hədd setSlowCallDurationThreshold vasitəsilə konfiqurasiya edilir.
Əsas StrictMode konfiqurasiyası 10 sətr kod tutur və fərdi Application sinfinin onCreate metodunda yerinə yetirilir. əas qayda: StrictMode yalnız debug build-lərdə aktivləşdirilir — release build-lərdə tətbiqi yavaşlatır və yalançı pozitivlər yarada bilər.
Application-dən miras alan sinif yaradın, onu AndroidManifest.xml-də android:name atributu ilə qeydiyyatdan keçirin və StrictMode konfiqurasiyasını əlavə edin. ThreadPolicy.Builder bütün detektorları və bütün penalty növlərini aktivləşdirir (dialog istisna olmaqla — yalnız debugger qoşulduqda işləyir). VmPolicy.Builder Activity və Closable sızıntı detektorlarını əlavə edir. Böyük layihələr (100+ ekran) üçün Activity Leaks detektorunda penaltyDeath ilə VmPolicy konfiqurasiya etmək tövsiyə olunur — bu sərt, lakin effektivdir.
class App : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectActivityLeaks()
.detectLeakedClosableObjects()
.detectLeakedRegistrationObjects()
.penaltyLog()
.penaltyDeath()
.build()
)
}
}
}
CI/CD-də avtomatik nəzarət üçün penaltyDeath istifadə edin — əgər hər hansı test siyasəti pozarsa, tətbiq istisna ilə çökəcək. Hər testin təmiz prosesdə işə düşməsi üçün Android Test Orchestrator ilə birləşdirin. UI testləri (Espresso, Compose Test) üçün StrictMode pozuntularını tutan və onları assertion failure-ə çevirən fərdi TestRule yazın. Nümunə: @Before-də StrictMode-u aktivləşdirin, @After-də violations olub-olmadığını yoxlayın.
Standart olaraq customSlowCall üçün hədd 2000 ms, disk_read və disk_write üçün isə hədd yoxdur (istənilən əməliyyat tetikleyir). setSlowCallDurationThreshold və setSlowIoDurationThreshold vasitəsilə millisaniyələrdə öz dəyərlərinizi təyin edə bilərsiniz. Tətbiqiniz əsas axında SharedPreferences-i qanuni olaraq oxuyursa (kiçik konfiq), həddi 10–20 ms-ə qədər artırın — bu, sürətli oxumaları kəsəcək, lakin yavaş olanları saxlayacaq.
StrictMode güclü, lakin şərtli bir alətdir. Yanlış konfiqurasiya milyonlarla yalançı pozitivə səbəb olur, buna görə tərtibatçılar onlara məhəl qoymurlar. Aşağıda — böyük Android komandalarının təcrübəsindən toplanmış yoxlanılmış təcrübələr.
Bu dəmir qaydadır: StrictMode HEÇ VAXT release build-lərdə aktiv olmamalıdır. BuildConfig.DEBUG bayrağından və ya fərdi buildConfigField-dən istifadə edin. Release build-lərdə çoxsaylı üçüncü tərəf kitabxanalar qanuni olaraq əsas axında əməliyyatlar yerinə yetirir (SDK başlatma, keş yazma) və StrictMode yalançı pozitivlər yaradacaq. Østəlik, penaltyDialog release build-də son istifadəçiyə dialoq göstərəcək — bu yolverilməzdir.
Kiçik layihələr (1–10 ekran) üçün penaltyLog konfiqurasiya edin — əl ilə analiz üçün loglar kifayətdir. Orta layihələr (10–50 ekran) üçün network və customSlowCalls üçün penaltyDeath əlavə edin. Böyük layihələr (50+ ekran) üçün CI/CD-də penaltyDeath ilə tam siyasət dəstini, yerli inkişaf üçün isə penaltyLog aktivləşdirin. Bu dərəcələnmə tərtibatçını yalançı crash-lərlə yükləməməyə, lakin pipeline-da keyfiyyəti sərt nəzarət etməyə imkan verir.
Bəzi kitabxanalar (Firebase, Crashlytics, Adjust) StrictMode-un səhv aşkarlaya biləcəyi əməliyyatları fonda qanuni yerinə yetirir. Həll yolları: kitabxananı penaltyListener vasitəsilə whitelist-ə əlavə edin, kitabxananı background thread-ə açıq keçid ilə versiyaya yeniləyin və ya StrictMode.vmPolicy istifadə edin. Android 11+-da stacktrace üzrə pozuntuların proqram filtrlənməsi üçün StrictMode.OnVmViolationListener meydana çıxdı.
// Yalançı pozitivlərin penaltyListener vasitəsilə filtrlənməsi
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyListener { violation ->
val stack = violation.stackTraceToString()
if ("com.google.firebase" !in stack) {
logViolation(violation)
}
}
.build()
)
StrictMode Android ekosistemində yeganə keyfiyyətə nəzarət aləti deyil. Onun yerini başa düşmək üçün onu Android Lint, Android Profiler və Perfetto ilə əsas meyarlar üzrə müqayisə edək: yoxlama vaxtı, analiz dərinliyi və avtomatlaşdırma.
| Meyar | StrictMode | Android Lint | Profiler / Perfetto |
|---|---|---|---|
| Yoxlama vaxtı | Runtime (tətbiq işləyərkən) | Compile time (işə salmadan əvvəl) | Runtime (post-mortem) |
| Nəyi yoxlayır | Disk, řəbəkə, sızıntılar | XML, kod, resurslar | CPU, yaddaş, řəbəkə, enerji |
| Avtomatlaşdırma | penaltyDeath ilə CI/CD | Gradle task + lint-baseline | Əl ilə analiz tələb edir |
| Dɗrinlik | Yalnız UI axını və sızıntılar | Statik kod analizi | Tam performans mənzərəsi |
| Yalançı pozitivlər | Orta (kitabxanalardan asılı) | Aşağı (konfiqurasiya edilmiş qaydalar) | Yox (real ölçülər) |
Ən yaxşı strategiya hürüç yanaşmanı birləşdirməkdir: Android Lint kompilyasiya mərhələsində aşkar səhvləri tutur (məsələn, unudulmuş IdleHandler), StrictMode problemləri real vaxtda aşkarlayır, Android Profiler / Perfetto isə ilk iki alət cavab vermədikdə dərin analiz üçün istifadə olunur. Real layihələrdə (Google Maps, Instagram) StrictMode inkişafın ikinci həftəsində — əsas arxitektura qurulduqdan dərhal sonra tətbiq edilir.
StrictMode-un performans problemlərini aşkarlamağa və aradan qaldırmağa kömək etdiyi iki real ssenariyə baxaq: əsas axında SharedPreferences oxunması və qeydiyyatdan keçirilməmiş callback vasitəsilə Activity sızıntısı.
Tətbiq başladıqda detectDiskReads siyasəti ilə StrictMode əsas axında SharedPreferences oxunmasını aşkarlayacaq. Həll yolu: konfiqurasiyanı CoroutineScope vasitəsilə asinxron yükləmək və ya başlanğıcda yaddaşda keşləmək. SharedPreferences sinxron olaraq diskdən XML faylı oxuyur — hətta kiçik faylda (1–2 KB) əməliyyat 1–5 ms, ucuz cihazlarda isə 20 ms-ə qədər çəkir və çərçivənin buraxılmasına səbəb ola bilər.
// ❌ Problemli kod — SharedPrefs-in UI axınında oxunması
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// StrictMode detectDiskReads → VIOLATION!
prefs = getSharedPreferences("config", MODE_PRIVATE)
}
}
// ✅ Düzəldilmiş kod — Coroutine vasitəsilə oxuma
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loadConfigAsync()
}
}
VmPolicy.detectActivityLeaks ilə StrictMode stekdən çıxmış (finish çağırılmış), lakin statik istinad və ya qeydiyyatdan keçirilməmiş callback səbəbindən Activity obyekti yaddaşda qalmağında davam edən Activity-ni aşkarlayacaq. Tipik ssenari: onResume-də EventBus və ya LocationListener qeydiyyatı onPause-də unregister çağırılmadan. VmPolicy istinadın yaradıldığı sətri göstərən stacktrace çap edəcək.
// ❌ Sızıntı — callback ləğv edilməyib
private var locationCallback: LocationCallback? = null
override fun onResume() {
super.onResume()
locationCallback = LocationCallback(this::onLocationUpdated)
locationManager.register(locationCallback) // StrictMode → LEAK!
}
override fun onPause() {
super.onPause()
// Unuduldu: locationManager.unregister(locationCallback)
}
Tez-tez verilən suallar
StrictMode həqiqətən də kiçik bir yük əlavə edir — hər bir sistem çağırışı siyasətlərə uyğunluq baxımından yoxlanılır. Performansa təsir debug build-də 1–3% təşkil edir və release-də (StrictMode söndürüldükdə) yoxdur. Köhnə cihazlarda (Android 6–8) detectAll aktivləşdirildikdə yük 5%-ə çata bilər, buna görə yalnız zəruri siyasətləri konfiqurasiya etmək tövsiyə olunur.
Bəli, StrictMode Jetpack Compose ilə tam uyğumludur. Disk və network siyasətləri UI çərçivəsindən asılı olmayaraq çərçivə səviyyəsində işləyir. Östəlik, Compose-da UI blokadasının kritikliyi daha yüksəkdir — Compose yüksək yeniləmə tezliyi olan cihazlarda 120 FPS tezliyi ilə çərçivələri yenidən çəkir, buna görə faylı oxumaq üçün əlavə 5 ms daha nəzərə çarpır.
Android 8.1-dən (API 27) başlayaraq SharedPreferences yaddaşda keşləmə istifadə edə bilər — əgər fayl artıq oxunubsa, təkrar oxuma StrictMode-u tetikləmir. getSharedPreferences-i ilk dəfə çağırdığınızı (soyuq oxuma) və detectDiskReads siyasətinin aktiv olduğunu yoxlayın. Həmçinin StrictMode-un parent-free fraqmentdə ləğv edilmədiyini yoxlayın.
JUnit testlərində @Before-də StrictMode.allowThreadDiskReads() və StrictMode.allowThreadDiskWrites(), @After-də isə StrictMode.enableDefaults() vasitəsilə parametrləri qaytarın. Instrumentation testləri üçün orijinal siyasəti müvəqqəti saxlayan fərdi TestRunner istifadə edin. Espresso testlərində StrictMode-a həssas kodu IdlingResource-də bükmək rahatdır.
StrictMode yalnız Android SDK vasitəsilə Android platformasında işləyir. Kotlin Multiplatform (KMP) commonMain kodu StrictMode-dan istifadə edə bilməz, lakin androidMain üçün onu həmişəki kimi əlavə edə bilərsiniz. iOS hissəsi üçün analoqdan istifadə edin — əsas axın üçün DispatchQueue.main.async assertion.
Nəticələr
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun