ANR in Android development — what it is, causes, and ways to fix it

Author: IT Sectr Published: 2026-03-28 Reading time: 9 min

ANR (Application Not Responding) is a system notification in Android that appears when an app stops responding to user input for more than 5 seconds. According to Android Developers, the main cause is long operations on the main thread that block touch processing and UI rendering. Understanding ANR mechanisms is essential for every Android developer to build responsive applications.

Key Takeaways

  • ANR — a system warning in Android when an app freezes for more than 5 seconds
  • Main thread (UI thread) — the only place where blocking leads to ANR
  • InputDispatcher — the system component that detects input delay and triggers ANR
  • traces.txt — the key file for diagnosing the cause of a freeze on a device
  • StrictMode — a built-in Android tool for detecting long operations on the UI thread

What is ANR

ANR (Application Not Responding) is a dialog box of the Android operating system that appears when an app stops responding to user input. The system tracks event processing time through InputDispatcher: if a touch or button press is not handled within 5 seconds, Android shows a dialog offering to close or wait for the app.

The ANR mechanism protects user experience from frozen apps. Android does not allow one app to block the entire system — unlike desktop OS, the mobile platform forcibly limits event processing time. BroadcastReceiver has a 10-second limit, and a foreground service has 20 seconds.

ANR is NOT an exception in code — it is a system mechanism at the Linux process level. Android sends a SIGQUIT signal to the process, after which the system saves the call stack of all threads to the traces.txt file. The developer does not receive ANR as a catch exception, but as a report after the app restarts. On Android 11+, the ApplicationExitInfo API allows programmatically getting the reason for process termination, including ANR — this simplifies statistics collection without manual traces.txt parsing.

Main causes of ANR

Five categories of operations consistently lead to ANR in Android applications. Each of them blocks the main thread, preventing the system from processing input events and screen redrawing.

Network requests on the main thread

Synchronous HTTP requests executed on the UI thread are the most common cause of ANR among beginner developers. Even a quick request to a server can take 1–3 seconds, and with a poor connection — 30 seconds or more. Android explicitly prohibits network operations on the main thread starting from API 11, throwing a NetworkOnMainThreadException.

Use Coroutines or RxJava for asynchronous calls. Coroutines with the Dispatchers.IO dispatcher execute the request on a background thread and pass the result to the main thread via Dispatchers.Main. This completely eliminates UI thread blocking by network operations.

kotlin
fun fetchUserData() {
    CoroutineScope(Dispatchers.Main).launch {
        val result = withContext(Dispatchers.IO) {
            api.getUserData() // background operation
        }
        updateUI(result) // result on the main thread
    }
}

Intensive computations on the UI thread

Processing large data arrays, parsing JSON or XML, working with bitmaps directly on the main thread — the second most frequent cause of ANR. Even 300 milliseconds of continuous UI thread work without returning to the event loop causes a noticeable rendering delay, and the threshold of 5 seconds is registered as ANR.

WorkManager and background services are designed to move heavy computations off the main thread. Use AsyncTask (deprecated), ListenableFuture, or Kotlin Flow to pass data in chunks without blocking the UI.

Synchronization locks and Deadlock

Deadlock occurs when two threads hold locks and wait for each other. If one of the threads is the main thread, the system registers ANR exactly after 5 seconds. Thread.join(), CountDownLatch.await(), and synchronized blocks called from the UI thread carry a blocking risk.

Avoid any blocking operations on the main thread. Instead of synchronized, use ConcurrentHashMap; instead of Thread.join() — coroutines with async/await. This rule applies to any language in Android: Java, Kotlin, or C++ via JNI.

Long-running BroadcastReceiver

BroadcastReceiver runs on the main thread by default. If onReceive() is busy for more than 10 seconds, Android shows ANR. Loading data from a database or network inside onReceive is a guaranteed path to freezing.

Use goAsync() inside BroadcastReceiver to switch to a background thread, or registerReceiver with getBackgroundBroadcastReceiver(). This allows handling events without blocking the UI.

ContentProvider and SQLite on the main thread

Heavy queries to ContentProvider or direct work with SQLite on the UI thread — a less obvious but common cause of ANR. During database migration or bulk insertion of thousands of records, execution time may exceed the 5-second limit.

Move all database operations to background threads using Room with suspend functions. Room automatically checks that the query is not executed on the main thread and throws an exception if violated.

How to diagnose ANR

Diagnosing ANR differs from debugging regular exceptions — you cannot catch ANR in a try-catch block. The main source of information is the traces.txt file, which Android creates at the moment of freezing.

traces.txt contains the call stack of all application threads at the time of ANR. To read the file from a real device, run the adb bugreport command, which collects a full system report including all ANRs from recent activity. For an emulator, the file is available at /data/anr/traces.txt. The call stack shows which method was executing on the main thread at the moment of blocking.

text
adb bugreport bugreport.zip
unzip -p bugreport.zip "*traces*" > traces.txt

Google Play Console provides the ANR & Crash section with aggregated reports and error frequencies. For each ANR, the call stack and device statistics are shown: model, Android version, region. This helps identify ANRs that depend on specific devices or system versions.

Android Studio since 2021 includes ANR Watchdog in the profiler. It automatically records thread dumps if the main thread does not respond for longer than a threshold time. The tool shows a timeline of events: which operations were started, which methods were executed, and at what stage the blocking occurred.

How to prevent ANR

Prevention of ANR is built on one fundamental rule: the main thread should only handle UI events. Any operation longer than 16 milliseconds (one frame time) should run on a background thread.

StrictMode — automatic checking

StrictMode is a built-in Android tool for detecting potential ANRs during development. Enable it in Application.onCreate() with flags for disk and network operations. When violated, StrictMode throws an exception or writes to logcat.

kotlin
if (BuildConfig.DEBUG) {
    StrictMode.ThreadPolicy.Builder()
        .detectDiskReads()
        .detectDiskWrites()
        .detectNetwork()
        .penaltyLog()
        .build()
        .let { StrictMode.setThreadPolicy(it) }
}

Asynchronous patterns: Coroutines and RxJava

Kotlin Coroutines — the standard way of asynchronous work in modern Android applications. The core approach: I/O operations run on Dispatchers.IO, the result is passed to Dispatchers.Main for UI updates. For Flow-like scenarios, use Dispatchers.Default for CPU-intensive tasks.

RxJava remains popular in legacy projects. subscribeOn(Schedulers.io()) and observeOn(AndroidSchedulers.mainThread()) — the minimum set for preventing ANR. The main rule is the same: no Observable or Flowable should emit data from the main thread.

Production monitoring

Firebase Crashlytics since SDK version 18.4.0 supports ANR monitoring out of the box. For Android 11+, Crashlytics uses the system API ApplicationExitInfo, which provides the exact termination reason: ANR, Crash, or system kill. Enable custom keys with screen and state parameters for contextual analysis.

Tools for ANR detection

Five tools cover all stages of working with ANR: from debugging on a workstation to monitoring in production. Each tool solves its own task and provides data for different scenarios.

ToolPurposeData format
StrictModeDetection during developmentLogcat / Exception
ANR Watchdog (Android Studio)Real-time tracingThread dump + timeline
Google Play ConsoleAggregated statisticsANR rate + stack traces
Firebase CrashlyticsProduction monitoringApplicationExitInfo
adb bugreportFull system reporttraces.txt + logcat + dmesg

Each tool has its own niche: StrictMode catches obvious violations early, Crashlytics shows the real ANR frequency among users, and adb bugreport provides the most complete picture for complex cases. Combine them for full coverage.

Firebase Performance Monitoring

Firebase Performance tracks UI thread response time and automatically creates traces for suspiciously long operations. If the main thread blocks for more than 500 ms, Performance records a custom trace with the name of the culprit method. This allows detecting ANR scenarios without user involvement and before they become critical.

Integration with Firebase Crashlytics provides a complete picture: Performance shows slowdowns before ANR, and Crashlytics shows the freeze itself. Set up alerts in Firebase Console for ANR rate above 0.1%, and you will receive notifications about new issues before mass user complaints.

Frequently Asked Questions

How is ANR different from Crash?

ANR is a freeze where the app does not respond but remains in memory. Crash is a complete abnormal termination with process exit. ANR can be “survived” if the system or user waits for a response, while Crash always terminates the app.

Can ANR be caught with try-catch?

No. ANR is not a Java/Kotlin exception but a system signal at the process level (SIGQUIT). A developer cannot handle it in application code. The only way to respond to ANR is to analyze reports after restart.

Why does ANR appear on some devices but not others?

Device performance, Android version, CPU load, and the number of background processes affect the likelihood of ANR. On weak devices, the same operation can take 2–3 times longer, exceeding the 5-second limit.

What is the BroadcastReceiver time limit before ANR?

10 seconds for a regular BroadcastReceiver in onReceive(). For foreground services, the limit is 20 seconds, and for ContentProvider — there is no explicit limit, but blocking the main thread for more than 5 seconds still causes ANR.

What to do if ANR occurs rarely and is not reproducible?

Enable StrictMode in all debug builds, add monitoring via Firebase Crashlytics, and use adb bugreport when ANR happens. Irregular ANRs are often related to race conditions or specific network states.

Summary

  • ANR — a system mechanism in Android triggered when the main thread blocks for more than 5 seconds
  • The main thread should only handle UI — all other operations should be moved to background threads
  • Diagnosis of ANR is done via traces.txt, Google Play Console, and Firebase Crashlytics
  • StrictMode detects potential ANRs during development without running on a real device
  • Coroutines with Dispatchers.IO — the standard way of asynchronous work in modern Android projects
  • BroadcastReceiver requires goAsync() or a background registrar to work longer than 10 seconds
  • ANR in production is monitored via Crashlytics and the built-in ApplicationExitInfo API on Android 11 and above

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also