Crash v mobilním vývoji: co to je, typy a metody prevence

Autor: IT Sectr Publikováno: 2026-03-29 Doba čtení: 9 min

Crash — nouzové ukončení mobilní aplikace kvůli neošetřené výjimce nebo fatální systémové chybě. Podle údajů Firebase Crashlytics se přibližně 2 % uživatelů denně setkává s pády a každý pád snižuje retenci o 10–20 %. Pochopení příčin a metod prevence pádů je povinnou dovedností pro mobilního vývojáře.

Hlavní body

  • Crash — neošetřená výjimka vedoucí k nouzovému ukončení procesu
  • NullPointerException — nejčastější typ pádu v aplikacích Java/Kotlin
  • Hlásiče pádů sbírají stack trace, stav zařízení a uživatelská data
  • Firebase Crashlytics — standardní nástroj pro monitorování pádů v mobilním vývoji
  • Prevence zahrnuje správné zpracování chyb, testování a kontrolu null-bezpečnosti

Co je Crash

Crash — je nouzové ukončení aplikace způsobené neošetřenou výjimkou nebo fatálním systémovým signálem, který nebyl zpracován v kódu aplikace. Když systém nebo virtuální stroj (JVM, ART) detekuje fatální stav — NullPointerException, IndexOutOfBoundsException, OutOfMemoryError — okamžitě zastaví proces a uvolní jej z paměti. Uživatel vidí náhlé zavření aplikace bez jakéhokoli systémového oznámení o chybě. Podle Google ztrácejí aplikace s crash-free mírou nižší než 99 % až 20 % aktivních uživatelů měsíčně.

Na Androidu se mechanismus zpracování pádů liší od desktopových systémů. Místo ladicího dialogu se stack trace Android jednoduše zabije proces a neukládá podrobné informace. Sběr informací o pádu je úkolem knihoven třetích stran (Crashlytics, Sentry, Bugsnag), které zachycují výjimky pomocí Thread.setDefaultUncaughtExceptionHandler předtím, než je proces ukončen.

iOS používá podobný mechanismus s NSException a Mach exceptions pro zpracování fatálních chyb. Při neošetřené výjimce systém ukončí aplikaci a zpráva se uloží jako soubor .crash. Sběr pádů na iOS vyžaduje integraci s Crashlytics nebo vestavěnou zprávou přes Xcode Organizer.

Hlavní typy pádů

Pět kategorií pádů pokrývá 90 % všech pádů v mobilních aplikacích. Pochopení každého typu pomáhá rychleji diagnostikovat a opravovat problémy v produkčním prostředí.

NullPointerException — král pádů

NullPointerException (NPE) — nejrozšířenější typ pádu ve všech aplikacích Java/Kotlin. Vzniká při pokusu o volání metody nebo přístup k poli objektu, který je null. Typické scénáře: neinicializované pole Activity při otáčení obrazovky, null odpověď ze serveru při deserializaci JSON, neopatrná navigace adaptérem RecyclerView.

Kotlin řeší problém NPE na úrovni jazyka pomocí null-bezpečných typů: String? nelze použít bez explicitní kontroly. Kompatibilita s Javou a Reflection však stále vytváří rizika. Používejte anotace @NonNull a @Nullable a zapněte strictNullChecks v nástrojích statické analýzy.

kotlin
fun safeLength(text: String?): Int {
    return text?.length ?: 0 // bezpečné zpracování null
}

IndexOutOfBoundsException a chyby kolekcí

IndexOutOfBoundsException vzniká při přístupu k neexistujícímu indexu seznamu nebo pole. Častý scénář: odstranění prvku z RecyclerView bez synchronizace s adaptérem, vícevláknová modifikace ArrayList bez zámku, nesprávný výpočet pozice v ViewPager. ConcurrentModificationException — blízký příbuzný při současné iteraci a modifikaci kolekcí.

Pro vícevláknový přístup použijte CopyOnWriteArrayList nebo Lock-free kolekce z java.util.concurrent. Pro synchronizaci s UI použijte DiffUtil, který bezpečně a efektivně vypočítává rozdíl mezi starým a novým seznamem.

ClassCastException — typové problémy

ClassCastException vzniká při převodu objektu na nekompatibilní typ. V Androidu typické příčiny: nesprávný typ ViewHolder v RecyclerView (různé typy buněk bez správného getItemViewType), nesprávný převod Fragmentu při navigaci, Serializable objekty s různými verzemi tříd.

Použijte bezpečný převod Kotlin pomocí operátoru as?, který vrací null při nekompatibilitě typů. V Javě — kontrola pomocí instanceof před převodem. U Parcelable objektů musíte v každé třídě deklarovat CREATOR.

IllegalStateException a logické chyby

IllegalStateException signalizuje volání metody v nevhodném stavu objektu. Typický příklad v Androidu — getSupportFragmentManager() po onSaveInstanceState, když commit() fragmentu není povolen. Další častý případ — volání dismiss() na již uzavřeném dialogu.

Před operacemi s FragmentManager zkontrolujte stav životního cyklu. Použijte commitAllowingStateLoss() pouze když jste si jisti, že ztráta stavu není kritická. V Kotlinu vytvářejte DSL-like stavitele, které vylučují nesprávné stavy na úrovni typů.

Native Crash (signály SIGSEGV, SIGABRT)

Native Crash vzniká v nativním kódu C/C++ při porušení paměti: přístup přes nulový ukazatel, double-free, přetečení zásobníkového bufferu. V Androidu k takovým pádům dochází v NDK knihovnách, herních enginech (Unity, Unreal) a systémových závislostech. Native Crash NENÍ zachycován Thread.setDefaultUncaughtExceptionHandler — okamžitě zabíjí proces.

Pro diagnostiku nativních pádů používejte minidump soubory (Breakpad) nebo Android tombstone. Firebase Crashlytics podporuje sběr nativních pádů přes NDK SDK. Na iOS se podobný problém řeší pomocí PLCrashReporter.

Nástroje pro hlášení pádů

Tři nástroje dominují na trhu hlášení mobilních pádů. Každý poskytuje sběr stack trace, agregaci podle verzí aplikace a upozornění na nové pády.

Firebase Crashlytics

Crashlytics — nejoblíbenější hlásič pádů pro mobilní aplikace, součást ekosystému Firebase. Automaticky sbírá stack trace, data o zařízení, verzi OS a uživatelské vlastní klíče. Integrace trvá 10 minut přes Firebase Console a Gradle Plugin. Crashlytics také podporuje skutečné logy (Logcat) a vlastní sledování.

kotlin
FirebaseCrashlytics.getInstance()
    .setCustomKey("current_screen", "ProfileFragment")

FirebaseCrashlytics.getInstance()
    .log("User tapped login button")

Sentry

Sentry — alternativa k Crashlytics s flexibilnějším systémem filtrování a podporou 90+ platforem. Na rozdíl od Firebase poskytuje Sentry vlastní server (self-hosted) pro společnosti s přísnými požadavky na data. Sentry podporuje distributivní sledování, breadcrumbs a integraci s CI/CD pipeline.

Bugsnag a AppCenter

Bugsnag se vyznačuje podporou upozornění založených na závažnosti: rozděluje pády na kritické, chyby a varování. AppCenter od Microsoftu — bezplatný nástroj se základní funkcionalitou pro malé projekty. Oba podporují Android, iOS, React Native a Flutter.

Jak analyzovat pád

Analýza pádu je proces rekonstrukce úplného obrazu události. Stack trace ukazuje pouze poslední bod selhání, ale neposkytuje kontext, který vedl k problému. Profesionální přístup zahrnuje čtyři fáze.

První fáze — čtení stack trace. Určete třídu, metodu a řádek kódu, kde došlo k výjimce. Sledujte řetězec volání od horního rámce dolů: poslední řádek v zásobníku je místo pádu a horní řádky jsou posloupnost volání. Deobfuskace (ProGuard/R8 mapping) je povinná pro produkční sestavení.

Druhá fáze — kontext zařízení. Crashlytics zobrazuje model zařízení, verzi OS, dostupnou paměť a verzi aplikace. Například pád pouze na Samsung Galaxy S10 s Androidem 11 ukazuje na problém s konkrétní verzí One UI, nikoli na obecnou chybu kódu.

Třetí fáze — reprodukce na testovacím zařízení. Pokud se pád stabilně nereprodukuje, zeptejte se uživatele na přesné kroky nebo použijte Remote Config pro logování před problematickou částí kódu. AB testování opravy na části publika pomáhá potvrdit řešení.

Čtvrtá fáze — monitorování po opravě. Po publikování opravy sledujte frekvenci pádu po dobu 3–5 dní. Pokud pád zcela zmizel — oprava fungovala. Pokud frekvence klesla, ale neklesla na nulu — existuje druhý scénář vyžadující samostatnou analýzu.

Postupy prevence pádů

Systémový přístup k prevenci pádů zahrnuje nástroje statické analýzy, povinné testování okrajových případů a správné zpracování chyb na všech úrovních aplikace.

Statická analýza kódu

Detekt (Kotlin) a Lint (Android) nacházejí potenciální problémy ve fázi kompilace: nepoužívané proměnné, potenciální NPE, nesprávné použití API. Zapněte tyto nástroje v CI pipeline s prahem chyb. Například Detekt s konfigurací 30+ varování nebo jakékoli error-blocking nepropustí sestavení.

Unit testy a UI testy

Pokrytí klíčových scénářů použití unit testy je základní ochranou proti regresním pádům. Testujte datové modely, ViewModel a UseCase vrstvy s okrajovými případy: null hodnoty, prázdné seznamy, neplatný JSON. UI testy přes Espresso nebo Compose Test pokrývají kritické toky: autentizace, platba, onboardig.

Graceful Degradation

Navrhujte aplikaci tak, aby selhání v jednom modulu nezbořilo celou obrazovku. Používejte catch bloky na úrovni ViewModel s vrácením záložního stavu: zobrazení placeholderu místo seznamu, data z cache při absenci sítě, záložní obrázek při chybě načítání. To mění potenciální pád v řízený UX scénář.

Postupné zavádění s monitorováním

Staged rollouts — standardní praxe Google Play a App Store: nová verze se distribuuje na 5 %, poté na 20 % a nakonec na 100 % publika s intervalem 1–3 dnů. V každé fázi se monitoruje frekvence pádů: pokud crash-free míra klesne pod 99,5 %, zavádění se automaticky zastaví. Firebase Remote Config umožňuje vypínat problematické funkce bez publikování nové verze.

Kontrola verzí závislostí

Renovate nebo Dependabot v CI automaticky kontrolují knihovny na známé zranitelnosti a kritické chyby. Aktualizace jedné závislosti může odstranit celou třídu pádů. Aktualizace však testujte na staging prostředí před nasazením do produkce — nová verze knihovny může obsahovat nekompatibilní změny.

Často kladené otázky

Lze předejít 100 % pádů?

Ne. Část pádů je způsobena faktory mimo kontrolu vývojáře: systémové chyby, hardwarové problémy, nekompatibilita firmwaru. Cílem je snížit frekvenci na 0,1 % a níže a zbývající pády minimalizovat z hlediska doby reakce.

Čím se liší hlásič pádů od analytiky?

Hlásič pádů sbírá stack trace, stav paměti a zařízení v okamžiku pádu. Analytika sbírá behaviorální data uživatele. Crashlytics kombinuje oba přístupy a poskytuje kontext pádu spolu s uživatelskými vlastními klíči.

Proč je stack trace obfuskovaný?

ProGuard a R8 obfuskují kód pro ochranu duševního vlastnictví. Pro deobfuskaci nahrajte mapping soubor do Crashlytics při publikování. Bez mapping souboru stack trace zobrazí a.a(), b.b() místo skutečných názvů tříd a metod.

Jak hlásič pádů zachycuje výjimky?

Pomocí Thread.setDefaultUncaughtExceptionHandler na Androidu: knihovna zaregistruje svůj vlastní handler, který jako první obdrží neošetřenou výjimku, uloží data a teprve poté ukončí proces. Na iOS se používá NSSetUncaughtExceptionHandler pro NSException a Mach exception handler pro signály.

Co je fatal a non-fatal pád?

Fatal — aplikace byla ukončena. Non-fatal (zachycená výjimka) — vývojář zachytil výjimku pomocí try-catch, ale to může naznačovat potenciální problém. Crashlytics tyto typy rozlišuje a umožňuje filtrovat non-fatal samostatně, aby nezanášel dashboard.

Shrnutí

  • Crash — nouzové ukončení aplikace kvůli neošetřené výjimce nebo fatálnímu signálu
  • NullPointerException zůstává nejčastějším typem pádu v mobilních aplikacích
  • Firebase Crashlytics — standardní nástroj pro sběr a analýzu pádů v produkci
  • Analýza pádu zahrnuje čtení stack trace, kontext zařízení a reprodukci v testovacím prostředí
  • Statická analýza (Detekt, Lint) předchází části pádů ve fázi kompilace
  • Graceful degradation mění potenciální pády na řízené scénáře se záložními daty
  • Mapping soubory jsou povinné pro deobfuskaci stack trace v produkčních sestaveních

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é