How to Fix ANRs in Android (Step-by-Step)
Learn how to debug and fix Android ANRs using trace analysis, profiling, StrictMode, background work, and production monitoring.
ANR stands for Application Not Responding. It’s Android’s way of telling you the app has become unresponsive for too long.
ANRs typically happen when the main thread (UI thread) is blocked and can’t respond to user input or system events. Even if your app doesn’t crash, ANRs are just as damaging because users experience them as frozen screens, taps not registering, or scrolling stuck—often ending with the “Wait / Close app” dialog.
This guide explains what causes ANRs, how to debug them properly, and how to eliminate them in production Android apps.
What causes ANRs in Android?
Most ANRs come from one of these categories:
Heavy work on the main thread
Examples include:
- database queries
- JSON parsing
- image decoding
- file I/O
- encryption or compression
Locks and thread deadlocks
Examples include:
- long synchronized blocks
- UI thread waiting for background tasks
- database locks under heavy concurrency
Binder or IPC calls that stall
Examples include:
- slow ContentProvider calls
- device services or system calls
- third-party SDK operations
Excessive work during app startup
Startup ANRs often appear when the app does too much inside:
Application.onCreate()- splash screen initialization
- dependency injection setup
Step 1: Confirm it’s really an ANR
Not every slow UI is an ANR.
ANR means Android detected your app was unresponsive long enough to trigger a system warning. Users often describe it like this:
“The app froze and Android asked me to close it.”
That’s an ANR.
Step 2: Get the ANR trace
The fastest way to debug ANRs is by reading the trace information.
You can usually find ANR reports in:
- Android Studio Logcat
- Google Play Console (Android Vitals)
- Firebase Crashlytics (if configured)
- device logs during local testing
The key is the main thread stack trace, which shows what your app was doing when it froze.
Step 3: Read the trace correctly
When you open an ANR trace, focus on these points:
Check the “main” thread first
If the main thread shows a call related to database access, file operations, loops, or blocking work, that’s likely the culprit.
Look for waiting or blocked states
Red flags include:
WAITINGBLOCKED- “waiting to lock…”
- deadlocks
This usually means the UI thread is waiting for another thread or resource.
Find the deepest call that belongs to your app
Framework calls can create noise. Look for lines that include:
- your app package name
- your repositories or DAOs
- parsing or utility logic
That’s where the fix usually belongs.
Step 4: Reproduce the ANR locally
Reproducing the issue is critical because it allows real fixes instead of guessing.
Ways to reproduce ANRs more reliably:
- test on low-end devices
- enable “Don’t keep activities” in Developer Options
- throttle the network
- test with large datasets and big file imports
Typical flows to test:
- cold start app launch
- opening heavy screens
- rapid navigation between screens
- importing or scanning large files
Step 5: Fix the most common ANR patterns
Most ANRs can be eliminated by applying the right fixes in the right place.
Fix 1: Move heavy work off the main thread
If you find any of these on the main thread:
- database queries
- JSON parsing
- reading/writing files
- cryptography or compression
Move them to background execution using Kotlin Coroutines and IO dispatchers. Your UI should only update state and render, not do heavyweight work.
Fix 2: Room / database ANRs
Room is safe until slow queries happen at the wrong time.
Common causes:
- huge queries returning large datasets
- joins producing very large results
- queries triggered repeatedly during navigation or UI updates
Fix patterns:
- add indexes for frequently filtered columns
- use paging for long lists
- reduce query size and return only needed fields
- avoid loading large entity graphs when unnecessary
Fix 3: Startup ANRs (Application.onCreate)
Startup ANRs happen when the app freezes before users even see the UI.
Common startup problems:
- initializing too many SDKs immediately
- heavy dependency injection setup
- synchronous access to disk or preferences
- database access during startup
Fix patterns:
- delay non-critical SDK initialization
- defer setup until after the first screen is shown
- move background tasks into WorkManager when appropriate
- load non-essential data later
Fix 4: Deadlocks and blocking on background work
A dangerous pattern is when:
- UI thread holds a lock
- background thread needs the same lock
- both wait, and the UI freezes
Fix patterns:
- reduce synchronized blocks
- avoid nested locking
- keep locks short and isolated
- consider lock-free concurrency where possible
Fix 5: Third-party SDK problems
Some ANRs come from SDKs that:
- block the UI during initialization
- do heavy work inside callbacks
- perform I/O on the main thread
Fix patterns:
- update the SDK version
- delay initialization
- isolate calls behind background execution
- measure the impact using profiling tools
Step 6: Use StrictMode during development
StrictMode can catch bad patterns early, such as:
- disk reads on the main thread
- disk writes on the main thread
- network calls on the main thread
It’s one of the best tools for preventing ANRs before they reach production.
Step 7: Monitor ANRs in production
ANRs often vary based on:
- device performance differences
- Android version behavior
- memory pressure
- background services
- real user data size
Track ANRs using:
- Google Play Console Android Vitals
- crash reporting dashboards
- performance monitoring tools
The best approach is always:
- identify the top ANR signature
- fix the root cause
- confirm the reduction in the next release
ANR Prevention Checklist
- ✅ Avoid disk and network work on the main thread
- ✅ Run database operations in background execution
- ✅ Use paging for long lists and large datasets
- ✅ Keep startup lightweight and defer non-critical work
- ✅ Delay heavy SDK initialization
- ✅ Enable StrictMode in debug builds
- ✅ Monitor ANRs after every release
FAQ
What is the fastest way to fix ANRs? Start by checking the main thread stack trace in the ANR report. In most cases, it clearly shows what blocked the UI thread.
Can Jetpack Compose cause ANRs? Compose usually causes frame drops and jank rather than ANRs. However, if the UI triggers blocking work like database access or file I/O during rendering, it can still lead to ANRs.
Are ANRs worse than crashes? In many cases, yes. Users experience ANRs as “the app is broken,” and they often uninstall even if the app doesn’t crash.
ANRs are not random. They are almost always caused by blocking work on the UI thread or incorrect concurrency patterns.
Once you build a habit of reading traces, reproducing issues locally, moving heavy work off the main thread, and monitoring production behavior, you can eliminate ANRs and keep your Android app fast and responsive.