Docs

Android ANR Rate Tracking

How to track Android ANR (Application Not Responding) rate, the thresholds Google Play enforces, and how it differs from crash tracking.

Performance

An ANR — Application Not Responding — happens when Android’s main thread is blocked for too long: a frozen input dispatch, a broadcast receiver that hangs, a service that never returns. Unlike a crash, the app doesn’t close; it just stops responding, and the OS eventually offers to force-quit it. That distinction is why ANRs get tracked separately from crash rate and why they’re just as damaging — a user staring at a frozen screen doesn’t care that the app is “technically still running.”

Google Play treats ANR rate as a first-class quality signal with hard thresholds: at least 0.47% of daily active users experiencing a user-perceived ANR across all device models is classed as poor, and 8% on any single device model triggers a warning independent of the aggregate number. Cross that line and Play Console can restrict your store listing’s visibility — this isn’t just a UX metric, it’s a distribution risk.

Data Points to Track

  • ANR count and rate: ANRs per session and per DAU, tracked separately from crash-free rate since they’re a different failure mode
  • Blocking call signature: the stack trace of what was running on the main thread when it froze, so ANRs group by root cause rather than by symptom
  • Device model and OS version: ANR rates vary widely by hardware — Play Console’s per-model 8% threshold means a single problematic device tier can tank your listing even if the aggregate rate looks healthy
  • Trigger context: what the user was doing immediately before the freeze (cold start, screen transition, background sync returning) since ANRs cluster around specific app states
  • Time-to-detection: how long after an ANR-causing regression ships before it’s flagged — a slow feedback loop lets a bad release sit in production for days before anyone notices
  • Foreground vs. background ANRs: whether the freeze was user-visible or happened while the app was backgrounded, since only user-perceived ANRs count against Play Console’s threshold

Setup Steps

  1. Enable main-thread block detection via Firebase Crashlytics, Sentry, or Datadog’s RUM integration — most modern SDKs flag a block once the main thread is unresponsive for roughly 5 seconds.
  2. Group ANRs by blocking call, not by device or timestamp, so recurring root causes (a specific database query, a synchronous network call) surface instead of getting lost in noise.
  3. Segment ANR rate by device model and compare against Play Console’s per-model 8% threshold weekly, since low-end and older devices are disproportionately affected.
  4. Add ANR rate to your release gate, alongside crash-free rate, so a regression is caught in a canary rollout rather than after full release.
  5. Cross-reference ANR spikes with recent deploys — most production ANR regressions trace back to a specific commit introducing a synchronous call on the main thread.

Actionable Insights

ANR data tells a different story than crash data: crashes usually point at edge cases and null states, while ANRs point at architectural problems — synchronous I/O, unbounded loops, or lock contention on the UI thread. A rising ANR rate with a flat crash rate is a strong signal that a recent change introduced blocking work where async was expected, even if nothing is technically broken.

Because Play Console enforces thresholds per device model as well as in aggregate, teams that only watch the headline number can pass the aggregate check while quietly failing on a popular budget device — the fix there is targeted performance work on that hardware tier, not a broad rewrite. Treat ANR rate as a release-blocking metric with the same seriousness as crash-free rate, not a secondary stat to check after the fact.

Expert help

Need help tracking this in your app?

Our team sets up analytics pipelines for mobile and web teams every day. Talk to us and get your first events flowing in under an hour.

Talk to an expert