ANR

On this page 7

ANR, short for Application Not Responding, is the condition in which Android detects that an app’s main thread has been blocked for too long to respond to user input or to complete a system callback. In mobile performance, an ANR is treated as a failure comparable to a crash: the user sees a frozen screen and, in the foreground case, a dialog offering to close the app or wait.

ANRs matter beyond the single frozen session. Android vitals in Google Play tracks the user-perceived ANR rate, and apps above the bad behavior threshold can receive reduced visibility in the store.

How Android detects an ANR

Every Android app has one main thread, also called the UI thread, which processes input events, draws frames and runs component lifecycle callbacks. The system sets a timeout whenever it hands the app a piece of work; if the app does not finish that work before the timeout expires, the system declares an ANR.

The timeouts differ by type of work. The table lists the commonly documented values; exact values can vary between Android versions and device configurations.

TriggerTimeoutWhat must finish
Input dispatch5 secondsResponse to a touch or key event
Foreground broadcast receiverAbout 10 secondsonReceive in a foreground broadcast
Background broadcast receiverAbout 60 secondsonReceive in a background broadcast
Foreground service startAbout 20 secondsService lifecycle callbacks
startForeground callAbout 10 secondsPromotion of a foreground service
Job executionPlatform-defined limitsResponding to job start or stop calls
Typical ANR timeouts on Android

When an ANR occurs, the system captures thread stack traces of the app’s process. These traces show what the main thread was doing at the moment of the timeout and are the starting point for every investigation.

Common causes of ANRs

Nearly every ANR comes down to work that does not belong on the main thread, or a main thread that waits for something it cannot get. The patterns below account for most cases in production.

CauseTypical stack trace signatureFix
Disk I/O on main threadFile, database or SharedPreferences callsMove I/O to a background dispatcher
Network on main threadSocket or HTTP client framesUse asynchronous networking
Lock contentionMain thread waiting on a monitorShorten locks, avoid sharing with slow work
DeadlockTwo threads waiting on each otherEnforce lock ordering
Slow app startupHeavy work in Application.onCreateDefer and lazily initialize
Binder call to busy system serviceBlocking IPC framesCall off the main thread or cache results
Frequent ANR causes and their signatures

A frequent hidden cause is synchronous SharedPreferences commits and database queries during lifecycle callbacks. They are fast on a new device with free storage but can take hundreds of milliseconds on an older phone with slow, nearly full flash memory.

An ANR is the extreme end of a spectrum of main-thread problems. Distinguishing it from neighboring issues helps teams pick the right tools and metrics.

IssueDuration of blockingUser experience
JankLonger than one frame, about 16 ms at 60 HzStuttering scroll or animation
Frozen frameLonger than about 700 msScreen visibly stops
ANRSeconds, beyond the timeoutDialog or forced close
CrashNot a blocking problemApp terminates with an exception
Slow app startupLong time to first frameBlank or splash screen lingers
ANR and neighboring performance issues

Crash analytics tools often collect ANRs together with crashes, but ANRs need different analysis: there is no exception, only a snapshot of blocked threads. Because the snapshot is taken at the timeout, the visible frame may be a victim, not the original culprit that started the delay.

Measuring and preventing ANRs

Production data comes mainly from Android vitals in the Play Console and from crash reporting SDKs. Android vitals reports the user-perceived ANR rate, the share of daily active users who experienced at least one ANR that they could notice. Google Play has used a bad behavior threshold of 0.47% overall and 8% on any single device model; teams should check the current values in the console.

Prevention combines development discipline with tooling:

  • StrictMode in debug builds flags disk and network access on the main thread.
  • Coroutines or executors move I/O and computation to background threads by default.
  • ApplicationExitInfo reports past ANRs with traces on Android 11 and later.
  • System tracing with Perfetto shows exactly where main-thread time goes.
  • Testing on low-end devices exposes delays that flagship phones hide.

A good working rule is to keep each main-thread task well below one frame and to treat any main-thread call that touches storage, network or another process as suspect.

Common mistakes when fixing ANRs

ANR fixes often fail because they treat the symptom. Increasing a timeout is not possible for most triggers and would only hide the problem. Wrapping slow code in a thread while the main thread still waits synchronously for its result produces exactly the same ANR.

Another mistake is to analyze only the top frame of one trace. Grouping many ANR reports by the full main-thread stack and checking what other threads held at the same time usually reveals the real lock or I/O bottleneck.

A plain-language summary

An ANR happens when an Android app freezes for several seconds and stops reacting to taps. The phone then shows a message saying the app is not responding and asks whether to close it or keep waiting.

Think of a shop with a single cashier. If the cashier leaves the counter to search the storeroom, the queue stops moving. After a while, customers give up. Good apps keep the cashier at the counter and send someone else to the storeroom.

An example from practice

A shopping app sees its user-perceived ANR rate climb to about 0.9% after a release, well above the store’s bad behavior threshold. Most reports come from budget phones with limited storage.

The grouped traces show the main thread waiting on a lock while a background thread rewrites a large preferences file. The new release had added a recently viewed products list to SharedPreferences and saved it synchronously on every screen change. The team moves the list to a database accessed from a background dispatcher and switches remaining preference writes to asynchronous apply calls.

Two weeks after the fix, the ANR rate falls to about 0.2%, and the app returns below the threshold. Store listing visibility recovers, and the team adds StrictMode checks to its debug builds to catch similar regressions before release.