Креш апликације — ванредни завршетак при којем програм престаје да одговара и затвара се. У мобилном развоју, крешеви су главни извор негативних рецензија и пада оцене Firebase (2024), корисници бришу апликацију након једног-два креша у 53% случајева. Свако затварање смањује задржавање за 3–5%. Системи за праћење попут Crashlytics-а и Sentry-ја помажу да се брзо пронађу и поправе узроци крешева пре масовног утицаја на кориснике.
Главно
Креш — неочекивани завршетак програма изазван изузетном ситуацијом коју код није обрадио. У мобилним ОС, креш доводи до тренутног затварања апликације и приказа екрана „Апликација је заустављена" или повратка на почетни екран
Крешеви се деле у две велике класе. Обрађене грешке — try/catch блокови хватају изузетак, апликација наставља да ради, могуће са губитком функционалности. Необрађени крешеви — изузетак се пропагира до нивоа ОС-а и систем убија процес. Други тип је посебно опасан јер корисник не може да сачува податке.
Систем са два милиона корисника и 0,1% crash rate-а губи 2 000 корисника на сваком издању. Према Google Play Console (2024), апликације са crash rate-ом изнад 1,5% се искључују из препорука и губе до 30% органског саобраћаја.
NullPointerException (NPE) — краљ крешева у Java/Kotlin-у. Покушај позива методе на null објекту. У Kotlin-у NPE се ређе јавља захваљујући null safety, али је и даље могућ при коришћењу оператора !! или интеракцији са Java кодом. Google (2024) процењује: NPE чини 25% свих крешева Android апликација.
IndexOutOfBoundsException — приступ елементу листе по непостојећем индексу. Чест узрок: подаци долазе са сервера у неочекиваном формату, а UI покушава да прикаже позицију која не постоји. undefined — увек провери величину колекције пре приступа по индексу.
ANR (Application Not Responding) — специфичан Android проблем. UI нит је блокирана више од 5 секунди. Главни узроци: мрежни захтеви на главној нити, тешка израчунавања, синхронизација са базом података. StrictMode у Android-у помаже у откривању блокирања UI нити у фази развоја.
OutOfMemoryError (OOM) — апликација је прекорачила ограничење меморије. На мобилним уређајима са 2–4 GB RAM-а, OOM је чест проблем при раду са великим сликама или бесконачним листама без пагинације. undefined — Glide/Coil за учитавање слика, LruCache за кеширање, ViewHolder у RecyclerView-у.
Runtime exceptions — грешке које компајлер не проверава у фази изградње. Оне се појављују само при извршавању кода на одређеном уређају са одређеним подацима. У Java-у су то RuntimeException и његове поткласе: NullPointerException, IllegalArgumentException, ArithmeticException.
Фаталне грешке (FATAL) — нису runtime, већ системски кварови. Signal 11 (SIGSEGV) — повреда сегментације меморије у native коду. Signal 6 (SIGABRT) — ванредни завршетак изазван самом апликацијом путем abort()-а. Такве крешеве је тешко дијагностиковати јер stack trace често не показује разумљив контекст.
У iOS-у главни узроци су NSInvalidArgumentException (неочекивани nil у параметру) и EXC_BAD_ACCESS (приступ ослобођеној меморији). Swift је смањио број крешева у поређењу са Objective-C-ом, али грешке у ObjC runtime-у и C библиотекама и даље доводе до падова.
Firebase Crashlytics — стандард за мобилне апликације. Аутоматски прикупља stack trace, додаје логове, ID корисника и метаподатке уређаја. Групише крешеве по потпису (класа грешке + линија). Real-time alerts — обавештења када crash rate пређе задати праг (нпр. >0,1% на сат).
Sentry — алтернатива са флексибилнијим могућностима. Омогућава креирање custom contexts-а, додавање breadcrumbs-а, подешавање in-app filtering-а за искључивање неважних грешака. Source maps за Kotlin и Swift омогућавају да се види изворни код, а не замагљена имена.
Best practices за логове: шаљи кључне метаподатке пре извршавања опасне операције. Додај custom keys (број верзије API-ја, последњи екран, величина улазних података). Ово претвара бескорисни stack trace у употребљиву информацију.
class PaymentViewModel : ViewModel() {
fun processPayment(amount: Double) {
crashlytics.setCustomKey("last_screen", "payment")
crashlytics.setCustomKey("amount", amount)
try {
api.charge(amount)
} catch (e: Exception) {
crashlytics.recordException(e)
}
}
}
Optional binding undefined null safety — у Kotlin-у користи `?` за nullable типове, `let` и `?:` за безбедну обраду null-а. У Swift-у — optionals и guard let. Modern Kotlin (2024) је додао Contract анотације: @ContractsDsl омогућава да се декларише да функција не враћа null, а компајлер то проверава.
Error handling undefined — сваки мрежни захтев мора да обради timeout, грешке парсирања и одбијање сервера. Retrofit undefined — sealed класа која гарантује да ће грешка бити обрађена. No Exception стил: уместо try/catch користи sealed Result за експлицитно руковање успехом и грешком.
Feature flags — искључи проблематичну функционалност даљински без објављивања нове верзије. Firebase Remote Config омогућава промену понашања апликације без објављивања у продавници.
Постепени rollout — објави нову верзију за 5% публике и прати crash rate. Ако rate остане испод циљаног (обично <0,1%), прошири на 25%, затим 50%, затим 100%. Google Play Console и App Store Connect подржавају phased rollouts за аутоматско заустављање при прекорачењу прага.
1: Класификација — одреди severity: Critical (креш код >1% корисника), High (0,1–1%), Medium (<0,1%). За Critical крешеве — одмах реаговати. Google Play Console аутоматски класификује крешеве по броју погођених корисника.
2: Анализа stack trace-а — отвори лог у Crashlytics-у, види тачно место пада. Провери custom keys: који екран, који подаци, верзија ОС-а. Упореди са последњим деплојем — често је креш изазван свежом променом у коду која је утицала на неочекивани сценариј употребе.
3: Репродукција — покушај да репродукујеш креш на уређају или емулатору са сличним параметрима. Ако не успе, провери crash log за обрасце: специфични модели (Samsung A10), Android верзије (API < 26), locale. undefined — додај заштитни услов који покрива сценариј.
4: Поправка и праћење — објави hotfix са приоритетом. Након објављивања увери се да crash rate за овај тип пада на нулу. Напиши регресиони тест који покрива сценариј креша. Без теста, исти баг се може вратити при следећем рефакторингу.
Често постављана питања
Нормални crash rate — мање од 0,1% за продукциона издања. Google Play препоручује одржавање crash rate-а испод 1,5%, али топ апликације (YouTube, Instagram) одржавају 0,01–0,05%. За издања нове функционалности дозвољен је привремени раст до 0,5% са накнадним смањењем након hotfix-а.
Креш — апликација се ванредно завршава. ANR (Application Not Responding) — апликација се замрзава на више од 5 секунди, али се не затвара насилно. Корисник види дијалог „Апликација не одговара" и може да сачека или затвори. ANR проблеми нису мање озбиљни од крешева и такође утичу на оцену у продавници.
Различити уређаји имају различите верзије ОС-а, количине меморије, верзије библиотека, па чак и процесоре. undefined: креш на Android 6 (API 23) због недостатка runtime дозволе можда се неће репродуковати на Android 12.
Додај custom breadcrumbs у Crashlytics: бележи кључне догађаје пре извршавања операције. Debug symbols (dSYM, ProGuard mapping) — обавезно отпреми у Crashlytics да би се видели стварни називи функција, а не замагљени.
У продукцији — никад. Необрађени крешеви погоршава корисничко искуство. Користи try/catch са логирањем грешке. У debug режиму, крешовање је дозвољено за брзу повратну информацију програмеру. Assertions — за проверу инваријанти које никада не смеју бити нарушене, али само у debug верзијама.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође