Android activities are the mechanism by which users can interact with your app. Most apps contain multiple screens, meaning they comprise multiple activities, and each activity can start another activity to perform different actions. Because of this, they’re liable to trigger Application Not Responding (ANR) errors when not correctly optimized.
ANRs are a complex problem to solve. In this series, we’re debunking some of the myths that mobile developers have come to know about how ANRs are triggered. In this blog, we’ll tackle Android activities. You can also check out our posts on broadcast receivers and services.
This blog post will answer the following questions:
- What is an Android activity?
- What triggers an ANR in an Android activity?
- What are common myths about Android activities and ANRs?
- How can you efficiently solve ANRs in your Android apps?
What is an Android activity?
An activity is a component that hosts some sort of user interface for user interaction. For example, an email app might have one activity that shows a list of new emails, another activity to compose an email, and yet another activity for reading emails.
What triggers an ANR in an Android activity?
Activities trigger an ANR if input dispatching takes more than 5 seconds. The Android OS interprets actions like touches, entries, or taps on the screen or keyboard as an “input event”. The OS then places these input events onto an input dispatch queue and processes them on the main thread, where a watchdog thread checks whether the processing takes more than 5 seconds. If the main thread is blocked or busy, the input dispatch queue will not empty within 5 seconds. At this point, the watchdog thread will trigger an ANR.
What are common myths about Android activities and ANRs?
In this section, we’ll dispel a few Android developers’ myths about monitoring and solving ANRs.
Myth #1: There is a 5-second threshold for an ANR to be triggered for activities
In reality, there is actually a 5-second threshold for ANRs to be triggered, but the timer only starts after an input event has been dispatched! That means your app could have a frozen main thread for much longer than five seconds, and the ANR timer won’t begin until the user makes an “input event”.
Myth #2: The Google Play Console and Firebase Crashlytics are the best sources of information for solving ANRs
In reality, your ranking and discoverability in the Google Play Store are affected when your app exceeds the bad behavior thresholds set by Google. You can learn more about them here, but there are two main thresholds you must be aware of:
- Overall bad behavior threshold: At least 0.47% of daily active users experience a user-perceived ANR across all device models.
- Per-device bad behavior threshold: At least 8% of daily users experience a user-perceived ANR for a single-device model.
While Google enforces that you meet these strict thresholds, the data it provides is often insufficient to get to the root cause of ANRs. Because the Google Play Console and Firebase Crashlytics only provide a stack trace after the ANR has been triggered, this data collection approach treats ANRs the same as crashes. However, a stack trace after 5+ seconds of being frozen could point to any number of root causes that don’t reflect what was happening when the app initially froze.
A more actionable approach to monitoring ANRs is capturing stack traces earlier during an app freeze. That way, developers get much closer to the code that was running that initiated the freeze.
Myth #3: An ANR that is triggered due to “input dispatching timed out” means an activity is to blame
In reality, since user input is associated with a UI (and thus activities), many mobile developers assume an “input dispatching timed out” ANR must be caused by an issue within an activity. However, the different Android components have different timing thresholds for triggering an ANR.
That means other components can block the main thread and resolve before reaching their threshold. If the freeze continues due to subsequently scheduled work, an ANR can easily trigger, and the stack trace will point the finger at the later component.
Since broadcast receivers, services, and activities all typically run on the main thread, they’re often running at the same time. Let’s cover an example where multiple components running can mask the real culprit behind an ANR.
This diagram shows a broadcast receiver that takes 6 seconds to complete while a user input event occurs at 1.5 seconds. The threshold for the broadcast receiver to trigger an ANR is 10 seconds, so the broadcast receiver finishes resolving before triggering an ANR. However, before the screen can unfreeze, an activity loads an image that blocks the main thread for another second, which now exceeds the 5-second “input dispatching timed out” threshold for an ANR. The stack trace captured by Google will highlight the activity’s `loadImage` method, but in reality, the freeze was caused by the broadcast receiver.
This example illustrates the core problems of relying on final stack traces to diagnose ANRs. They frequently do not show the complete picture, so mobile teams need visibility into the entire duration of app freezes to truly understand what causes them.
How can you efficiently solve ANRs in your Android apps?
Session-based monitoring is a different approach from event-based monitoring solutions. It favors understanding the complete technical details of entire user experiences in order to significantly expand the types of issues you can solve.
With session-based monitoring, your mobile team can benefit from the context of full user sessions, including every activity/fragment, network call, log, device state change, breadcrumb, error, and more. Instead of trying to piece together what led to an issue, your team has complete visibility into every user experience. For example, when investigating ANRs, a session-based monitoring solution can provide:
- Earlier freeze detection and stack trace capture (as early as 1 second)
- Multiple stack trace capture to understand how the code evolved throughout an ANR
- ANR grouping by package to surface the worst offenders in first- and third-party code
- Flame graphs to quickly highlight the most common code execution paths in aggregate across every ANR stack trace
This level of diagnostic detail is simply not possible with traditional mobile monitoring approaches. For more information, check out our Solving ANRs 101 eBook to learn the true relationship between ANRs and the Android framework, including how session-based monitoring can better help you identify and eliminate ANRs in your app!