ANR Debugging & Prevention

📖 Concept

ANR (Application Not Responding) occurs when the main thread is blocked for too long:

  • Input event: 5 seconds without response
  • BroadcastReceiver.onReceive(): 10 seconds
  • Service.onCreate()/onStartCommand(): 20 seconds (foreground), 200 seconds (background)

Common causes:

  1. Disk I/O on main thread — SharedPreferences.commit(), file reads, database queries
  2. Network on main thread — synchronous HTTP calls (rare now but still happens)
  3. Heavy computation — JSON parsing, image processing, complex algorithms
  4. Deadlocks — Two threads waiting for each other's locks
  5. Slow ContentProvider queries — Unindexed database queries
  6. Binder calls — Synchronous IPC to a slow system service

Debugging ANRs:

  1. Logcat: Look for "ANR in" messages with the process and reason
  2. traces.txt: adb pull /data/anr/traces.txt — Shows stack trace of ALL threads at ANR time
  3. StrictMode: Enable disk/network detection in debug builds
  4. Android Vitals (Play Console): Shows ANR rate and stack traces from production
  5. Perfetto: System-wide tracing for complex threading issues

Google's guideline: ANR rate should be below 0.47% (less than 1 ANR per 200 user sessions).

💻 Code Example

codeTap to expand ⛶
1// Common ANR causes and fixes
2
3// ANR: SharedPreferences.commit() on main thread ❌
4fun saveUserPreference(key: String, value: String) {
5 prefs.edit().putString(key, value).commit() // Blocks main thread!
6}
7// FIX: Use apply() or DataStore
8fun saveUserPreference(key: String, value: String) {
9 prefs.edit().putString(key, value).apply() // ✅ Async write
10}
11
12// Even better: Use DataStore
13class PreferencesRepository @Inject constructor(
14 private val dataStore: DataStore<Preferences>
15) {
16 suspend fun savePreference(key: String, value: String) {
17 dataStore.edit { prefs -> prefs[stringPreferencesKey(key)] = value }
18 }
19
20 fun getPreference(key: String): Flow<String?> {
21 return dataStore.data.map { it[stringPreferencesKey(key)] }
22 }
23}
24
25// ANR: Database query on main thread ❌
26fun getUser(id: String): User {
27 return database.userDao().getById(id) // Blocks if DB is slow!
28}
29// FIX: Use suspend + Dispatchers.IO
30suspend fun getUser(id: String): User = withContext(Dispatchers.IO) {
31 database.userDao().getById(id)
32}
33
34// ANR: Deadlock detection
35// Thread A holds lock1, waits for lock2
36// Thread B holds lock2, waits for lock1
37// Both threads blocked forever — ANR if main thread is involved
38
39// Prevention: Always acquire locks in the same order
40class SafeLocking {
41 private val lock1 = ReentrantLock()
42 private val lock2 = ReentrantLock()
43
44 // Always acquire lock1 before lock2 — prevents deadlock
45 fun operation() {
46 lock1.withLock {
47 lock2.withLock {
48 // Safe — consistent lock ordering
49 }
50 }
51 }
52}
53
54// StrictMode for development-time detection
55if (BuildConfig.DEBUG) {
56 StrictMode.setThreadPolicy(
57 StrictMode.ThreadPolicy.Builder()
58 .detectDiskReads()
59 .detectDiskWrites()
60 .detectNetwork()
61 .detectCustomSlowCalls()
62 .penaltyLog()
63 .penaltyDeath() // Crash on violation in debug
64 .build()
65 )
66}

🏋️ Practice Exercise

Practice:

  1. Enable StrictMode and find all main-thread disk/network violations in your app
  2. Analyze an ANR traces.txt file — identify the blocked thread and root cause
  3. Replace all SharedPreferences.commit() calls with apply() or DataStore
  4. Implement a custom ANR watchdog that detects main thread blocking
  5. Check your app's ANR rate on Google Play Console

⚠️ Common Mistakes

  • Using SharedPreferences.commit() instead of apply() — commit() writes synchronously to disk on the calling thread

  • Querying ContentProviders without a background thread — some providers (Contacts, MediaStore) can be slow

  • Not monitoring ANR rates in production — by the time users complain, your ANR rate may be critical

  • Running Room database operations without specifying a background dispatcher

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for ANR Debugging & Prevention. Login to unlock this feature.