Introduction
ANR (App Not Responding) issues are one of the most common and frustrating problems Android developers face, especially after major Android updates like Android 14. An ANR happens when an app becomes unresponsive for a certain amount of time, and the system shows a popup asking the user to close the app or wait.
In simple words, an ANR means the app is doing too much work on the main thread and is unable to respond to user actions quickly. Android 14 introduces stricter performance monitoring, better system diagnostics, and tighter background execution rules, which makes ANRs more visible if apps are not well optimized.
This article explains how developers debug ANR issues on Android 14 devices, step by step, using simple language and real-world examples.
What Causes ANR Issues on Android 14
Before debugging, it is important to understand why ANRs happen.
Common causes include:
Long-running operations on the main (UI) thread
Network calls executed on the main thread
Heavy database queries are blocking the UI
Deadlocks or thread contention
Broadcast receivers are taking too long to finish
Services are doing excessive work without proper threading
On Android 14, the system is more strict about detecting these issues, so apps that were previously "just working" may now trigger ANRs.
Understanding ANR Time Limits
Android triggers an ANR when certain time limits are exceeded.
Typical limits include:
UI thread blocked for about 5 seconds
BroadcastReceiver not finished within about 10 seconds
Service not responding within a defined timeout
Android 14 enforces these limits more consistently, especially on low-memory or heavily loaded devices.
Checking ANR Reports in Google Play Console
One of the first places developers look is the Google Play Console.
The Play Console provides:
Example insight:
You may see that most ANRs happen on Android 14 devices during app startup, which hints at heavy initialization code on the main thread.
This data helps developers prioritize which ANRs to fix first.
Reading ANR Stack Traces
ANR reports include stack traces that show what the main thread was doing when the ANR occurred.
A typical ANR trace shows:
Example of a simplified ANR stack trace:
"main" prio=5 tid=1 Blocked
at java.lang.Object.wait(Native Method)
at com.example.app.DatabaseHelper.loadData(DatabaseHelper.java:85)
at com.example.app.MainActivity.onCreate(MainActivity.java:42)
This tells the developer that database loading is blocking the UI during app startup.
Using Logcat to Investigate ANRs
Logcat is a powerful tool for debugging ANRs during development and testing.
Developers typically filter logs using:
adb logcat | grep ANR
Or check system logs:
adb logcat ActivityManager:E *:S
These logs often show warnings before the ANR occurs, such as skipped frames or long operations on the main thread.
StrictMode for Early Detection
StrictMode helps developers catch performance issues during development before users experience ANRs.
Example of enabling StrictMode:
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build()
)
StrictMode warns developers when disk access, network calls, or long operations run on the main thread.
Using Android Studio Profiler
Android Studio Profiler is one of the best tools to debug ANRs on Android 14.
Developers use it to:
Example workflow:
Start the app, reproduce the ANR scenario, and observe CPU spikes or long-running methods on the main thread.
Identifying Main Thread Blocking Code
Most ANRs are caused by blocking the main thread.
Common mistakes include:
Database queries in onCreate()
File I/O on the UI thread
Synchronous network requests
Bad example (blocking UI):
val data = database.loadAllData()
textView.text = data.toString()
Better approach (background thread):
lifecycleScope.launch {
val data = withContext(Dispatchers.IO) {
database.loadAllData()
}
textView.text = data.toString()
}
Debugging BroadcastReceiver ANRs
BroadcastReceivers have very strict execution time limits.
If heavy work is required, developers should move logic to a background worker.
Bad example:
override fun onReceive(context: Context, intent: Intent) {
performHeavyTask()
}
Better approach:
override fun onReceive(context: Context, intent: Intent) {
WorkManager.getInstance(context)
.enqueue(OneTimeWorkRequest.from(HeavyWorker::class.java))
}
Handling ANRs in Services
Services can also trigger ANRs if they perform heavy work on the main thread.
Developers should:
Example using background execution:
CoroutineScope(Dispatchers.IO).launch {
processData()
}
Testing on Real Android 14 Devices
Emulators do not always show real-world ANR behavior.
Developers should test on:
This helps catch timing and performance issues that cause ANRs in production.
Monitoring Frame Drops and UI Jank
ANRs often follow severe UI jank.
Android Studio provides frame rendering data that shows:
Skipped frames
Long render times
UI thread overload
Fixing UI jank often prevents ANRs before they happen.
Preventing ANRs Proactively
Instead of only reacting to ANRs, developers should design apps defensively.
Best practices include:
Keep UI thread work minimal
Use background threads for heavy tasks
Defer non-critical initialization
Use efficient data loading strategies
Test under real-world conditions
Summary
Developers debug ANR issues on Android 14 by analyzing ANR reports, reading stack traces, using Logcat, enabling StrictMode, and profiling apps with Android Studio tools. Most ANRs are caused by blocking the main thread with heavy operations. Android 14 enforces performance rules more strictly, making proper threading, background execution, and testing essential. By moving heavy work off the UI thread and using modern debugging tools, developers can significantly reduce ANRs and improve app stability on Android 14 devices.