StrictMode: co to je, režim přísných pravidel a debugging v Androidu

Autor: IT Sectr Publikováno: 2026-03-31 Doba čtení: 8 min

StrictMode je vestavěný vývojářský nástroj v Android SDK, který v reálném čase detekuje a hlásí náhodné I/O operace a síťová volání v hlavním vlákně aplikace. Neopravuje chyby, ale funguje jako detektor — vyhazuje výjimky nebo zapisuje do LogCat, když dojde k porušení nastavených politik. Podle údajů Google, 2024 umožňuje správné nastavení StrictMode odhalit až 80 % problémů s výkonem ještě před vydáním aplikace.

To hlavní

  • StrictMode — detektor porušení výkonu v hlavním vlákně Androidu
  • Politiky disku (disk_read, disk_write) a sítě (network) tvoří základní sadu kontrol
  • Nástroj neopravuje problémy, ale upozorňuje na ně přes LogCat, dialog nebo crash
  • Nastavení probíhá v Application.onCreate a používá setThreadPolicy + setVmPolicy
  • Penalty režimy: vyhození výjimky (death), logování, upozornění do dropboxu

Co je to StrictMode

StrictMode je API, které je součástí Android SDK od API Level 9 (Android 2.3 Gingerbread). Jeho úkolem je v runtime odhalovat náhodné provádění těžkých operací v hlavním (UI) vlákně, které mohou zablokovat vykreslování rozhraní. Hlavní vlákno zodpovídá za zpracování uživatelského vstupu, výpočet layoutu a vykreslování — jakékoli zablokování delší než 16 ms vede k vynechání snímku.

Filozofie nástroje

StrictMode se řídí principem „fail fast“ — odhalit problém co nejdříve, nejlépe v okamžiku jeho prvního výskytu. Místo čekání na stížnosti uživatelů na zpomalení dostává vývojář signál (logy, dialog nebo crash) přímo ve fázi vývoje. Nástroj nevyžaduje další knihovny ani konfiguraci Gradle — stačí pár řádků kódu v Application.onCreate a funguje automaticky na všech zařízeních.

Cílová skupina

StrictMode je určen pro všechny vývojáře pro Android, bez ohledu na zkušenosti. Začátečníkům pomáhá vytvořit si správné návyky (nedělat síťové požadavky v UI vlákně), zkušeným umožňuje automatizovat kontrolu kvality v CI/CD pipeline. Velké projekty (Google, Uber, Spotify) zapínají StrictMode v debug verzích s penaltyDeath a v release verzích ho vypínají pomocí kontroly BuildConfig.DEBUG.

Jak funguje StrictMode

StrictMode zachycuje systémová volání, která mohou blokovat vlákno, a porovnává je se sadou aktivních politik. Pokud volání odpovídá politice a probíhá v hlavním vlákně, StrictMode aplikuje nastavenou penalizaci. Mechanismus zachycení je implementován přes hook uvnitř procesu — nepoužívá reflection a pracuje s minimální režií.

Mechanismus detekce

Při aktivaci politiky StrictMode vkládá svůj handler do vstupního bodu systémových volání (FileInputStream, FileOutputStream, Socket, URLConnection). Když aplikace zavolá například URLConnection.openStream v hlavním vlákně, StrictMode zkontroluje aktuální vlákno — pokud jde o main thread, nástroj se spustí. Od Androidu 6.0+ je mechanismus posílen: síťová volání v main thread generují NetworkOnMainThreadException i bez StrictMode, ale StrictMode umožňuje kontrolovat i disk I/O.

Penalty (trest)

Každá politika může mít vlastní typ penalizace nebo jejich kombinaci: penaltyLog — zápis do LogCat se stacktrace, penaltyDialog — zobrazení dialogu uživateli (jen v debug), penaltyDeath — vyhození výjimky a crash aplikace, penaltyDropBox — uložení dat do DropBoxManager pro pozdější analýzu. Pro CI/CD pipeline se doporučuje penaltyDeath — to zaručuje, že žádný merge s porušením nezůstane bez povšimnutí.

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()
                    .penaltyLog()
                    .penaltyDeath()
                    .build()
            )
        }
    }
}

Politiky StrictMode

StrictMode rozděluje politiky na dvě úrovně: ThreadPolicy (vláknové — co se nesmí dělat v hlavním vlákně) a VmPolicy (virtuálního stroje — úniky paměti a zdrojů). Obě úrovně se nastavují nezávisle a fungují paralelně.

ThreadPolicy: disk a síť

Na úrovni vlákna StrictMode kontroluje čtyři typy porušení: čtení z disku (detectDiskReads), zápis na disk (detectDiskWrites), síťové operace (detectNetwork) a uživatelská pomalá volání (detectCustomSlowCalls). disk_read se spustí při jakémkoli čtení SharedPreferences, SQLite nebo souborů v hlavním vlákně. network — při HTTP požadavcích, WebSocket, Socket připojeních. V Androidu 11+ byl přidán detectUnbufferedIO pro odhalení nebuferovaného I/O.

VmPolicy: úniky paměti

VmPolicy kontroluje úniky na úrovni virtuálního stroje ART: detectActivityLeaks (Activity, které nebyly zničeny), detectLeakedClosableObjects (nezavřené Cursor, Stream, Socket), detectLeakedRegistrationObjects (nezrušené BroadcastReceiver, ServiceConnection). Pokud VmPolicy zjistí, že Activity byla vytvořena, ale po volání onDestroy nebyla zničena, vypíše plný stack trace — to šetří hodiny ladění úniků paměti.

PolitikaÚroveňCo detekuje
detectDiskReadsThreadČtení SharedPrefs, SQLite, souborů v UI vlákně
detectDiskWritesThreadZápis do SharedPrefs, SQLite, souborů v UI vlákně
detectNetworkThreadJakékoli síťové operace v UI vlákně
detectActivityLeaksVMActivity, které přežily onDestroy
detectLeakedClosableObjectsVMNezavřené Cursor, Stream, Socket

Uživatelské štítky (customSlowCall)

Přes detectCustomSlowCalls lze vlastní metody označit jako „podezřelé“ a dostávat varování při překročení nastaveného prahu. Například pokud vaše metoda loadUserProfile() obvykle trvá 5 ms, ale v některých případech 200 ms, obalte ji do StrictMode.noteSlowCall("loadUserProfile"). Pokud doba překročí práh (ve výchozím nastavení 2000 ms), StrictMode vygeneruje penalizaci. Práh se nastavuje přes setSlowCallDurationThreshold.

Jak nastavit StrictMode

Základní nastavení StrictMode zabere 10 řádků kódu a provádí se v metodě onCreate vlastní třídy Application. Hlavní pravidlo: StrictMode se zapíná pouze v debug verzích — v release verzích zpomaluje aplikaci a může vytvářet falešná spuštění.

Základní konfigurace

Vytvořte třídu, která dědí z Application, zaregistrujte ji v AndroidManifest.xml přes atribut android:name a přidejte konfiguraci StrictMode. ThreadPolicy.Builder zapíná všechny detektory a všechny typy penalizace (kromě dialog — ten funguje jen při připojeném debuggeru). VmPolicy.Builder přidává detektory úniků Activity a Closable objektů. Pro velké projekty (100+ obrazovek) se doporučuje nastavit VmPolicy s penaltyDeath na detektor Activity Leaks — je to přísné, ale účinné.

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            StrictMode.setVmPolicy(
                StrictMode.VmPolicy.Builder()
                    .detectActivityLeaks()
                    .detectLeakedClosableObjects()
                    .detectLeakedRegistrationObjects()
                    .penaltyLog()
                    .penaltyDeath()
                    .build()
            )
        }
    }
}

Integrace do CI/CD

Pro automatickou kontrolu v CI/CD použijte penaltyDeath — pokud nějaký test poruší politiku, aplikace spadne s výjimkou. Kombinujte s Android Test Orchestrator, aby každý test běžel v čistém procesu. Pro UI testy (Espresso, Compose Test) napište vlastní TestRule, který zachycuje porušení StrictMode a přeměňuje je na selhání assertion. Příklad: v @Before zapněte StrictMode a v @After ověřte, že nedošlo k žádným violations.

Nastavení prahů

Ve výchozím nastavení je práh pro customSlowCall 2000 ms, pro disk_read a disk_write není žádný (spustí se jakákoli operace). Přes setSlowCallDurationThreshold a setSlowIoDurationThreshold lze nastavit vlastní hodnoty v milisekundách. Pokud vaše aplikace legitimně čte SharedPreferences v hlavním vlákně (malá konfigurace), zvyšte práh na 10–20 ms — to odfiltruje rychlá čtení, ale ponechá pomalá.

Osvědčené postupy StrictMode

StrictMode je výkonný, ale náladový nástroj. Nesprávné nastavení vede k milionu falešných spuštění, kvůli kterým jim vývojáři přestanou věnovat pozornost. Níže jsou osvědčené postupy nasbírané ze zkušeností velkých Android týmů.

Zapínejte pouze v debug verzích

Toto je železné pravidlo: StrictMode NIKDY nesmí být aktivní v release verzích. Použijte příznak BuildConfig.DEBUG nebo vlastní buildConfigField. V release verzích mnoho knihoven třetích stran legitimně provádí operace v hlavním vlákně (inicializace SDK, zápis cache) a StrictMode vytvoří falešná spuštění. Navíc penaltyDialog v release verzi zobrazí dialog koncovému uživateli — což je nepřípustné.

Používejte tři úrovně přísnosti

Pro malé projekty (1–10 obrazovek) nastavte penaltyLog — logy stačí pro ruční analýzu. Pro střední projekty (10–50 obrazovek) přidejte penaltyDeath na network a customSlowCalls. Pro velké projekty (50+ obrazovek) zapněte plnou sadu politik s penaltyDeath v CI/CD a pro lokální vývoj penaltyLog. Tato gradace nepřetěžuje vývojáře falešnými crashy, ale přísně kontroluje kvalitu v pipeline.

Zpracování false positives

Některé knihovny (Firebase, Crashlytics, Adjust) legitimně provádějí operace na pozadí, které StrictMode může chybně detekovat. Řešení: přidejte knihovnu do whitelist přes penaltyListener, aktualizujte knihovnu na verzi s explicitním přepnutím na background thread, nebo použijte StrictMode.vmPolicy. V Androidu 11+ se objevil StrictMode.OnVmViolationListener pro programovou filtraci porušení podle stacktrace.

kotlin
// Filtrace false positives přes penaltyListener
StrictMode.setThreadPolicy(
    StrictMode.ThreadPolicy.Builder()
        .detectAll()
        .penaltyListener { violation ->
            val stack = violation.stackTraceToString()
            if ("com.google.firebase" !in stack) {
                logViolation(violation)
            }
        }
        .build()
)

StrictMode vs Android Lint vs profilery

StrictMode není jediný nástroj kontroly kvality v Android ekosystému. Abyste pochopili jeho místo, porovnejme ho s Android Lint, Android Profiler a Perfetto podle klíčových kritérií: doby kontroly, hloubky analýzy a automatizace.

KritériumStrictModeAndroid LintProfiler / Perfetto
Doba kontrolyRuntime (během běhu aplikace)Compile time (před spuštěním)Runtime (post-mortem)
Co kontrolujeDisk, síť, únikyXML, kód, zdrojeCPU, paměť, síť, energie
AutomatizaceCI/CD přes penaltyDeathGradle task + lint-baselineVyžaduje ruční analýzu
HloubkaJen UI vlákno a únikyStatická analýza kóduÚplný obraz výkonu
Falešná spuštěníStřední (závisí na knihovnách)Nízká (nastavená pravidla)Žádná (skutečná měření)

Nejlepší strategií je kombinovat všechny tři přístupy: Android Lint chytá zjevné chyby ve fázi kompilace (například zapomenutý IdleHandler), StrictMode detekuje problémy v runtime a Android Profiler / Perfetto se používá pro hloubkovou analýzu, když první dva nástroje nedají odpověď. V reálných projektech (Google Maps, Instagram) se StrictMode zavádí ve druhém týdnu vývoje — hned po nastavení základní architektury.

Příklady kódu se StrictMode

Podíváme se na dva reálné scénáře, kde StrictMode pomáhá odhalit a odstranit problémy s výkonem: čtení SharedPreferences v hlavním vlákně a únik Activity přes neregistrovaný callback.

Detekce pomalých SharedPreferences

Při startu aplikace StrictMode s politikou detectDiskReads odhalí čtení SharedPreferences v hlavním vlákně. Řešení: načítat konfiguraci asynchronně přes CoroutineScope nebo ji při startu cachovat do paměti. SharedPreferences synchronně čte XML soubor z disku — i při malém souboru (1–2 KB) operace trvá 1–5 ms, na levných zařízeních až 20 ms, což může vést k vynechání snímku.

kotlin
// ❌ Problémový kód — čtení SharedPrefs v UI vlákně
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // StrictMode detectDiskReads → VIOLATION!
        prefs = getSharedPreferences("config", MODE_PRIVATE)
    }
}

// ✅ Opravený kód — čtení přes Coroutine
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loadConfigAsync()
    }
}

Odhalení úniku Activity

StrictMode s VmPolicy.detectActivityLeaks odhalí Activity, která opustila zásobník (byl zavolán finish), ale objekt Activity nadále visí v paměti kvůli statické referenci nebo neregistrovanému callbacku. Typický scénář: registrace EventBus nebo LocationListener v onResume bez volání unregister v onPause. VmPolicy vypíše stacktrace s uvedením řádku, kde byla reference vytvořena.

kotlin
// ❌ Únik — callback nebyl zrušen
private var locationCallback: LocationCallback? = null

override fun onResume() {
    super.onResume()
    locationCallback = LocationCallback(this::onLocationUpdated)
    locationManager.register(locationCallback) // StrictMode → LEAK!
}

override fun onPause() {
    super.onPause()
    // Zapomněli jste: locationManager.unregister(locationCallback)
}

Často kladené dotazy

Zpomaluje StrictMode aplikaci?

StrictMode skutečně přidává mírnou režii — každé systémové volání se kontroluje na soulad s politikami. Dopad na výkon je 1–3 % v debug verzi a v release chybí (kde je StrictMode vypnut). Při zapnutí detectAll na starších zařízeních (Android 6–8) může režie dosáhnout 5 %, proto se doporučuje nastavit pouze potřebné politiky.

Lze použít StrictMode s Jetpack Compose?

Ano, StrictMode je plně kompatibilní s Jetpack Compose. Politiky disk a network fungují na úrovni frameworku, nezávisle na UI frameworku. Navíc v Compose je kritičnost UI blokování vyšší — Compose překresluje snímky frekvencí 120 FPS na zařízeních s vysokou obnovovací frekvencí, proto je 5 ms navíc na čtení souboru znatelnější.

Proč StrictMode nereaguje na čtení SharedPreferences?

Od Androidu 8.1 (API 27) může SharedPreferences používat cache v paměti — pokud byl soubor již přečten, opakované čtení nespustí StrictMode. Zkontrolujte, že getSharedPreferences voláte poprvé (studené čtení) a že je aktivní politika detectDiskReads. Zkontrolujte také, že StrictMode není přepsán v parent-free fragmentu.

Jak vypnout StrictMode pro jednotlivé testy?

V JUnit testech použijte StrictMode.allowThreadDiskReads() a StrictMode.allowThreadDiskWrites() v @Before a v @After vraťte nastavení přes StrictMode.enableDefaults(). Pro Instrumentation testy použijte vlastní TestRunner s dočasným uložením původní politiky. V Espresso testech je vhodné kód citlivý na StrictMode obalit do IdlingResource.

Je StrictMode potřeba v Kotlin Multiplatform?

StrictMode funguje pouze na platformě Android přes Android SDK. V Kotlin Multiplatform (KMP) nemůže kód commonMain používat StrictMode, ale pro androidMain ho můžete přidat jako obvykle. Pro iOS část použijte analog — DispatchQueue.main.async assertion pro hlavní vlákno.

Shrnutí

  • StrictMode — runtime detektor problémů s výkonem v hlavním vlákně Androidu
  • Politiky se dělí na ThreadPolicy (disk, síť) a VmPolicy (úniky paměti)
  • Nastavení zabere 10 řádků kódu v Application.onCreate s kontrolou BuildConfig.DEBUG
  • Pro CI/CD použijte penaltyDeath — porušení politiky vede k pádu aplikace
  • StrictMode nenahrazuje, ale doplňuje Android Lint a Perfetto
  • Správná filtrace false positives je klíčem k efektivnímu použití nástroje
  • Doporučuje se zavést StrictMode ve druhém týdnu vývoje projektu

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také