What is ANR (Application Not Responding) in Android?

Nishil Patel

Nishil Patel

Feb 6, 2025

6 min read

Share

What is ANR (Application Not Responding) in Android?

In Android, an ANR occurs when your app's main thread is blocked for too long, causing the system to consider it unresponsive. This typically results in the infamous “ANR” dialog that prompts you to either wait or force close the app. Learn more about ANRs in this article.

Table of Contents

1.

Introduction

2.

What Blocks the UI Main Thread Causing ANR Errors

3.

How to Diagnose ANR Errors

4.

How to Fix the Error

5.

How to Prevent ANRs

6.

FAQs

Introduction

While you may be using the latest and greatest Android device, sometimes, things can still go haywire with your apps and the dreaded “Application not responding (ANR)” error shows up on your screen. The app freezes inadvertently, preventing you from interacting with it anyway and leaving you with a bad user experience.

In this article, learn more about what causes ANR errors, practical ways to diagnose and fix them when they occur, and how to prevent them from showing up for your apps.

Application not responding (ANR)

Image Source: ANRs | Android Developers Portal

What is ANR (Application Not Responding)?

ANRs occur when an Android application's main UI rendering thread is either blocked or takes too long to respond (usually over five seconds). 

This error primarily occurs when the main UI thread is unable to process user inputs (like touch interactions or key presses) or complete background tasks before the 5-second timeout. This makes the Graphical User Interface (GUI) unresponsive. As a result, the system displays an ANR dialog box giving you the option to either:

  • Force close the app or 
  • Wait for it to respond. 

Also ReadHow to Fix “JavaScript Heap Out of Memory” Error

What Blocks the UI Main Thread Causing ANR Errors

Let’s look at the common conditions that clog up the UI thread, thus triggering this error:

Long-running Operations on the Main Thread

As described, Android’s main thread does all the heavy lifting for completing UI rendering tasks like processing touch interactions or key presses. Problems arise when an app takes too long to process:

  • Network calls (due to slow server speeds) 
  • Frequent database queries and response handling
  • CPU-intensive I/O operations (storage operations)
  • Circular referencing in application code
  • Long-running or infinite loops
  • Complex calculations

As a result, the user input processing gets delayed, thus, forcing the error.

Input Dispatching Timed Out

If the app gets too busy processing other background tasks and a delay of five seconds or more happens for handling user input events, the UI thread gets blocked, thus triggering the ANR dialogue box.

Service Execution Delays

As per Android ground rules, an app needs to finish executing service methods: Service.onCreate()Service.onStartCommand(), or Service.onBind(), that have initially been declared by it. Even a few seconds delay to complete these operations results in an error message.

Delay in Calling the Service.startForegound() Method

If your app code has the Context.startForgoundService() method that’s already declared initially for starting a foreground service, but the startForeground() method doesn’t get called within the five-second window, it throws an error.

Broadcast Receiver Execution Delays

When a BroadcastReceiver hasn’t been executed within a specified time frame (within five seconds) for starting an activity in the foreground, it can lead to an ANR. It typically occurs when the:

  • onRecieve() method hasn't finished executing in the stipulated timeframe.
  • On the PendingResult object, there’s a failed call to the finish() method just after a call has been made to the goAsync() method.

Delay in Interacting with the JobService Methods

Even a few seconds delay in returning from the methods JobService.onStartJob() or JobService.onStopJob() can clog the main thread, thus forcing the ANR dialogue. Besides this, if there’s a delay in calling the JobService.setNotification() method just after the JobService.onStartJob() has finished executing, this too, causes the error to show.

How to Diagnose ANR Errors

Here are a few things to check:

  • Slow Operations on the Main Thread — Your app takes too long to complete I/O operations on the main thread.
  • Long Calculations — If you see your app frequently does long calculations on the main thread.
  • Delayed Return from the Binder Method —  A delayed return from a method necessary for the main thread to execute a synchronous binder call indicates a potential issue.
  • Blocked Thread — The main thread is stuck, waiting for a long task to finish on another thread (that’s synchronized with the main thread).
  • Deadlock â€” Check for any deadlock instances. These happen when two or more threads are waiting for each other to release resources, causing all threads to freeze simultaneously.

Create Perfect Bug Reports for Devs in One-click

How to Fix the Error

Once you’re good with the diagnosis, you can use the following fixes to resolve the issue:

Fix 1: Optimize Code for Faster Execution 

Check for places in your code where the main thread’s execution speed appears to be taking more than five seconds to complete. For instance, most of the ANRs happen when the onClick(view) handler gets executed by the main thread. To solve this, assign these slow-running handler executions for the Worker Threads instead of the main thread. You can do this by using Android framework classes. 

Example Code in Java

Before

@Override
public void onClick(View view) {
    // Task on main thread
    DataProcessor.process(dataSet);
}

After

@Override
public void onClick(View view) {
    // Offload processing to a background thread
    new Thread(() -> {
        List<ItemType> processedData = DataProcessor.process(dataSet);
        // Update UI on main thread
        runOnUiThread(() -> {
            renderView(processedData);
        });
    }).start();
}

Example Code in Kotlin

Before

override fun onClick(v: View) {
    // Task on main thread
    DataProcessor.process(dataSet)
}

After

override fun onClick(v: View) {
    // Offload processing to a background coroutine
    CoroutineScope(Dispatchers.Default).launch {
        val processedData = DataProcessor.process(dataSet)
        // Update UI on main thread
        withContext(Dispatchers.Main) {
            renderView(processedData)
        }
    }
}

Fix 2: Move I/O Operations for the Worker Thread

This fix is similar to offloading slow-executing code and methods to worker threads for completion. Moving I/O operations like handling network calls and storage operations for the worker thread to handle should do the trick.

Example Code in Java

Before

void retrieveData() {
    String content = dataFetcher.fetchContent(); // I/O on main thread
    displayContent(content);
}

After

void retrieveData() {
    new Thread(() -> {
        String content = dataFetcher.fetchContent(); // I/O on a separate thread
        runOnUiThread(() -> {
            visualizeContent(content); // Update UI on the main thread
        });
    }).start();
}

Example Code in Kotlin

Before

fun retrieveData() {
    val content = dataFetcher.fetchContent() // I/O on main thread
    displayContent(content)
}

After

fun retrieveData() {
    CoroutineScope(Dispatchers.IO).launch {
        val content = dataFetcher.fetchContent() // I/O on background thread
        withContext(Dispatchers.Main) {
            visualizeContent(content) // Update UI on the main thread
        }
    }
}

Fix 3: Resolve Lock Contentions

Sometimes, when a worker thread holds a lock on a resource, the operation is offloaded to the main thread to complete, causing it to block and leading to an ANR error. This refers to lock contention. And this could pose problems with the main thread’s code execution ability.

To resolve lock contention:

  1. Use the Android Device Monitor to check the main thread's status. The status can be: BLOCKED, RUNNING, WAIT, and MONITOR. Based on the status, check the system traces to identify the code causing the block and modify it accordingly.
  2. Use mechanisms like onProgressUpdate() and onPostExecute() for better syncing between the worker and main threads.

Example Code in Java

Before

private synchronized void manipulateResource(String value) {
    // Operation that takes time
    sharedValue = value;
}

public void onUserAction() {
    manipulateResource("Incoming Value"); // Called from UI thread
}

After

private final Object resourceGuardian = new Object();

private void manipulateResource(String value) {
    new Thread(() -> {
        synchronized (resourceGuardian) {
            // Time-consuming operation
            sharedValue = value;
            runOnUiThread(() -> {
                // Optionally, refresh the view
                refreshView();
            });
        }
    }).start();
}

public void onUserAction() {
    manipulateResource("Incoming Value"); // Invokes the threaded method
}

Fix 4: Resolve Deadlocks

In the case of deadlocks, use deadlock prevention algorithms (such as the Banker’s Algorithm) to steer clear of circular dependencies. Besides this, maintain a strict order in which threads can use resources to prevent circular waiting.

NOTE: Deadlocks are notoriously difficult to debug and should be avoided through careful design. You can use techniques like resource ordering and avoiding unnecessary synchronization to prevent deadlocks.

Fix 5: Resolve Slow-running Broadcast Receivers

To fix slow broadcast receivers:

  1. It’s best to defer complex tasks to IntentService instead of doing them in the onReceive() method to move the long-running operation to a worker thread.
  2. Make sure that the finish() method is always called on the PendingResult object when using goAsync(). Note that goAsync() gives you a short window (typically 10 seconds) to complete your work, even on a background thread.
  3. Consider using the onReceive() method for short operations only.
  4. Use tools like CPU Profiler to identify any long-running tasks on the main thread and resolve broadcast receiver issues.

Example Code in Java

Before

public class NotificationListener extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Lengthy operation
        processNotification(intent.getExtras());
    }
}

After

public class NotificationListener extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        PendingResult taskResult = goAsync();
        new Thread(() -> {
            handleNotification(intent.getExtras());
            taskResult.finish();
        }).start();
    }
}

Example Code in Kotlin

Before

class NotificationListener : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        // Lengthy operation
        processNotification(intent.extras)
    }
}

After

class NotificationListener : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        goAsync().also { asyncTask ->
            CoroutineScope(Dispatchers.IO).launch {
                handleNotification(intent.extras)
                asyncTask.finish()
            }
        }
    }
}

How to Prevent ANRs

Here are a few ways to prevent ANRs in your Android app:

Use Android Vitals from the Google Play Console 

You can use Android Vitals from the Google Play Console to monitor your app's technical performance, including ANR Rates in production apps. Specifically, the user-perceived ANR rate is a core vital that can affect your app’s discoverability on Google Play. Monitoring these metrics helps you identify and fix issues that impact user experience and your app's visibility.

Use Perfetto for UI Responsiveness Profiling 

Use Perfetto to analyze UI responsiveness and pinpoint performance bottlenecks. It’s a powerful profiling tool for Android apps. While Systrace can also be used, Perfetto offers more advanced features and a better interface. You can use Perfetto to visualize main thread activity, identify slow code, and optimize for smoother performance, thus minimizing the risk of ANRs. It’s highly recommended for most developers.

Avoid Synchronous Binder Calls

Synchronous code calls to other processes that may take a long time to return can cause ANRs. Avoiding these in your code can help minimize ANRs. Using asynchronous operations works best for tasks that could take a long time to complete.

Strict Mode

Use StrictMode during development to find accidental I/O operations on the main thread. StrictMode helps identify areas of the code that may perform long-running operations on the main thread for you to refactor and improve performance.

Use Efficient Data Structures and Algorithms 

Optimize code logic to minimize execution time for operations performed on the main thread.

Handle Lock Contention Properly

Review and refactor code that might cause lock contention between threads; consider using more granular locking mechanisms or lock-free data structures.

Use Coroutines in Kotlin

Coroutines provides a structured way to manage background threads and perform asynchronous programming in Kotlin. This can help avoid ANRs.

Implement Timeouts for Critical Operations

Set reasonable timeouts for operations that could hang indefinitely, allowing for graceful error handling.

FAQs

The ANR rate in Android refers to the frequency at which an app experiences "Application Not Responding" (ANR) errors. This rate is an important metric for developers, as a high ANR rate can negatively affect the app’s performance and user experience. It can also impact the app's ranking and discoverability in the Google Play Store. Monitoring and minimizing the ANR rate is crucial to ensure the app remains responsive and performs well.

Written by

Nishil Patel | CEO & Founder

Follow

Nishil is a successful serial entrepreneur. He has more than a decade of experience in the software industry. He advocates for a culture of excellence in every software product.

Subscribe to our updates

Meet the Author: Nishil Patel, CEO, and Co-founder of BetterBugs. With a passion for innovation and a mission to improve software quality.

We never spam.

Nothing here!
Show us some love 💖. Try BetterBugs today if you haven’t already. A quick feedback and a rating on our Chrome web store page would be awesome!

Share your experience with the founderhere!

Don’t wait! Start reporting now.