ANR (Application Not Responding) ist eine Systembenachrichtigung in Android, die erscheint, wenn eine App innerhalb von 5 Sekunden nicht auf Eingaben reagiert. Im Gegensatz zu Glitches (logische Fehler ohne UI-Blockierung) und Lags (Verlangsamung ohne vollständigen Stopp) ist ANR ein kritischer Fehler, der vom Betriebssystem aufgezeichnet wird: Android zeigt einen Dialog „App antwortet nicht“ mit der Option zum Schließen oder Warten an. Laut Android Vitals Documentation erhalten Apps mit einer ANR-Rate über 0,5 % eine niedrigere Bewertung im Google Play und können aus den Empfehlungen ausgeblendet werden. Die Diagnose umfasst die Analyse von /data/anr/traces.txt, die Verwendung von StrictMode und das Profiling des Hauptthreads.
Wichtige Punkte
ANR (Application Not Responding) ist ein Benutzerschutzmechanismus in Android, der ausgelöst wird, wenn die App nicht mehr auf Eingaben reagiert. Das System verfolgt die Ereignisverarbeitungszeit: Wenn BroadcastReceiver onReceive nicht innerhalb von 10 Sekunden abschließt, Service nicht innerhalb von 20 Sekunden von onCreate zurückkehrt oder ContentProvider nicht innerhalb von 15 Sekunden antwortet — generiert Android einen ANR.
Wenn ein ANR auftritt, zeigt Android einen Systemdialog über allen Fenstern an: „App antwortet nicht. Möchten Sie sie schließen oder warten?“ Der Benutzer kann die App schließen oder auf ihre Wiederherstellung warten. Wenn ANRs häufig auftreten, deinstalliert der Benutzer die App. Google Play berücksichtigt die ANR-Rate — den Prozentsatz der Sitzungen mit ANR — in seinen Ranking-Algorithmen.
iOS hat kein Äquivalent zu ANR mit einem Systemdialog. Stattdessen verwendet Apple Watchdog, der den Prozess mit dem Exit-Code 0x8badf00d beendet. Der Benutzer sieht keinen Dialog — die App wird einfach zum Startbildschirm geschlossen. Dies macht ANR auf Android für den Benutzer sichtbarer, gibt dem System aber mehr Diagnoseinformationen.
ANR tritt auf, wenn das System ein Timeout für einen der vier Komponententypen verfolgt. Jede Komponente hat ihr eigenes Zeitlimit.
BroadcastReceiver wird im Hauptthread ausgeführt. Wenn onReceive eine synchrone Netzwerkanfrage, einen langen Datenbank-Schreibvorgang startet oder auf eine Sperre wartet — tritt innerhalb von 10 Sekunden ein ANR auf. Lösung: Verwenden Sie goAsync() und WorkManager für die Hintergrundverarbeitung. Ein typisches Szenario ist der Empfang einer Push-Benachrichtigung von FCM und das synchrone Speichern in Room.
Service.onCreate und Service.onStartCommand haben ein Limit von 20 Sekunden. Wenn der Dienst eine schwere Initialisierung (Laden von Bibliotheken, Lesen der Konfiguration aus dem Netzwerk) im Hauptthread startet — ist ANR unvermeidlich. Verwenden Sie IntentService (veraltet) oder WorkManager für eine garantierte Ausführung im Hintergrund.
ContentProvider.onCreate wird vor Application.onCreate ausgeführt und hat ein Limit von 15 Sekunden. Wenn der Provider eine Datenbankmigration durchführt, Wörterbücher lädt oder das SDK aus dem Netzwerk initialisiert — verursacht dies ANR beim App-Start. Lösung: Lazy-Initialisierung, Auslagern schwerer Operationen an WorkManager.
Android bietet mehrere Tools für die ANR-Analyse: von Systemprotokollen bis zu spezialisierten Bibliotheken.
Bei jedem ANR speichert Android die Datei /data/anr/traces.txt mit einem Stack-Dump aller App-Threads. Suchen Sie den Thread „main“ — die letzte Methode im Stack gibt die Ursache an. Typische Muster: Thread.sleep(), InputStream.read(), BinderProxy.transact(). Zum Extrahieren der Datei vom Gerät verwenden Sie adb mit Superuser-Rechten.
Firebase Crashlytics sammelt ANRs automatisch und zeigt sie im Dashboard mit Traces an. Für Android 11+ enthalten ANR-Berichte den vollständigen Stack des Hauptthreads. Die Integration erfordert das Hinzufügen einer Abhängigkeit und die Initialisierung von FirebaseApp in Application.onCreate.
CPU Profiler in Android Studio ermöglicht es Ihnen, App-Traces aufzuzeichnen und zu sehen, welche Methoden CPU-Zeit beanspruchen. Aktivieren Sie „Record with method traces“ und reproduzieren Sie das Szenario, das den ANR verursacht. Die Zeitleiste zeigt, welche Methoden zum Zeitpunkt des Einfrierens im Hauptthread ausgeführt wurden.
Beispiel für die Integration von Firebase Crashlytics zur ANR-Erfassung auf Android:
class App : Application() {
override fun onCreate() {
super.onCreate()
FirebaseApp.initializeApp(this)
FirebaseCrashlytics.getInstance()
.setCrashlyticsCollectionEnabled(true)
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build())
}
}
ANR zu beheben bedeutet in erster Linie, alle langlaufenden Operationen vom Hauptthread in Hintergrundthreads zu verlagern. Sehen wir uns spezifische Techniken für jeden Komponententyp an.
WorkManager ist Googles empfohlene Lösung für Hintergrundarbeit. Er garantiert die Aufgabenausführung in einem Hintergrundthread unter Berücksichtigung des Gerätezustands. Im Gegensatz zu Service blockiert WorkManager den Hauptthread nicht und ist resistent gegen App-Neustarts. Für BroadcastReceiver verwenden Sie goAsync() und übergeben das PendingResult an WorkManager.
Führen Sie alle Netzwerkanfragen, Datenbankoperationen und Datei-E/A mit Dispatchers.IO aus. Der Hauptthread sollte nur die UI aktualisieren. Verwenden Sie viewModelScope für die automatische Kündigung von Coroutinen beim Zerstören der Activity. Vermeiden Sie runBlocking() in jedem Kontext — es blockiert den aktuellen Thread synchron.
Wenn ContentProvider eine langsame Initialisierung durchführt, verwenden Sie einen Lazy-Loading-Mechanismus: Erstellen Sie einen Provider, der sofort Daten zurückgibt, und starten Sie die schwere Initialisierung über WorkManager mit einer Verzögerung. Dies verhindert ANR beim App-Start, wenn das System am empfindlichsten auf Verzögerungen reagiert.
Beispiel für die korrekte Verwendung von BroadcastReceiver mit goAsync in Android:
class FcmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val pendingResult = goAsync()
WorkManager.getInstance(context!!)
.enqueue(OneTimeWorkRequest.from(NotificationWorker::class.java))
pendingResult.finish()
}
}
Der beste Weg, ANRs zu bekämpfen, ist, sie während der Entwicklung durch Tools und architektonische Entscheidungen zu verhindern.
StrictMode mit aktivierten Richtlinien detectNetwork() und detectDiskReads()/detectDiskWrites() identifiziert potenzielle ANRs während der Entwicklung. Setzen Sie in Debug-Builds penaltyDeath — jeder Verstoß führt zu einem sofortigen Absturz, und der Entwickler sieht das Problem vor dem Commit.
Firebase Performance verfolgt die Ausführungszeit wichtiger Operationen und zeigt, welche Szenarien den ANR-Schwellenwert überschreiten. Richten Sie benutzerdefinierte Traces für jeden Bildschirm und jede Netzwerkanfrage ein. Wenn die Ausführungszeit 3 Sekunden überschreitet — handelt es sich um einen potenziellen ANR, der optimiert werden muss.
Simulieren Sie langsame Bedingungen: Begrenzen Sie die Netzwerkgeschwindigkeit mit Network Link Conditioner auf iOS oder Android Emulator. Verlangsamen Sie das Lesen von der Festplatte durch Emulation langsamen Speichers. ANR treten oft gerade unter solchen Bedingungen auf; auf schnellen Entwicklergeräten sind sie unsichtbar.
Häufig gestellte Fragen
Android verfolgt explizit die Ereignisverarbeitungszeit im Hauptthread und zeigt einen ANR-Dialog an. iOS verwendet Watchdog, der die App bei einem Einfrieren von mehr als 10–20 Sekunden zwangsweise schließt. ANR ist ein Merkmal der Android-Architektur, bei der mehrere Komponenten (BroadcastReceiver, Service) strenge Timeouts haben.
Unter Android 11+ können Sie den ANR-Dump über adb shell dumpsys dropbox --print data_app_anr abrufen. Unter Android 10 und früher ist ohne Root-Zugriff kein Zugriff auf /data/anr/traces.txt möglich. Verwenden Sie Firebase Crashlytics — es sammelt ANR-Berichte automatisch für Android 11+.
Google Play empfiehlt eine ANR-Rate unter 0,5 % — nicht mehr als 5 ANRs pro 1000 Sitzungen. Eine App mit einer Rate über 1 % erhält eine Warnung in der Google Play Console und kann aus den Empfehlungen ausgeblendet werden. Idealerweise sollte die ANR-Rate unter 0,1 % liegen.
Eine Coroutine an sich blockiert den Thread nicht. Aber wenn innerhalb einer Coroutine runBlocking im Hauptthread ausgeführt wird oder die Coroutine mit Dispatchers.Main gestartet wird und eine lange CPU-Operation ausführt — verursacht dies ANR. Verwenden Sie Dispatchers.IO für E/A und Dispatchers.Default für Berechnungen.
Verwenden Sie Android Emulator mit einem „Slow Network“-Profil oder schreiben Sie einen Test, der Thread.sleep(6000) im Hauptthread aufruft. Starten Sie die App über Debug und nach 5 Sekunden sehen Sie den ANR-Dialog. Überprüfen Sie, ob logcat einen ANR-Eintrag mit Trace anzeigt.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch