Ошибки anr что это

Время на прочтение
4 мин

Количество просмотров 26K

ANR (Application Not Responding) — ошибка, которая возникает, когда приложение не отвечает. В итоге открывается диалоговое окно, предлагающее пользователю подождать или закрыть приложение.
image alt

Условия возникновения ANR

  • Входные события (кнопки и сенсорные события) не обрабатываются в течение 5 секунд;
  • BroadcastReceiver (onRecieve()) не был обработан в течение указанного времени (foreground — 10 с, background — 60 с);
  • ContentProvider не завершен в течение 10 секунд.

Обычно основной поток блокируется.

Если вы читали мои статьи, то наверно уже привыкли к тому, что мы лезет в исходный код. Так что давайте посмотрим как выглядит ANR под капотом.

Класс AppErrors занимается обработкой не только ANR, но и других ошибок, которые могут возникнуть в приложении, включая crash. Метод handleShowAnrUi() как раз и открывает это страшное для многих разработчиков и пользователей окно, отображающее ANR.

class AppErrors {
    ...
    
    void handleShowAnrUi(Message msg) {
        Dialog dialogToShow = null;
        synchronized (mService) {
            AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
            final ProcessRecord proc = data.proc;
            if (proc == null) {
                Slog.e(TAG, "handleShowAnrUi: proc is null");
                return;
            }
            if (proc.anrDialog != null) {
                Slog.e(TAG, "App already has anr dialog: " + proc);
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                        AppNotRespondingDialog.ALREADY_SHOWING);
                return;
            }

            Intent intent = new Intent("android.intent.action.ANR");
            if (!mService.mProcessesReady) {
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                        | Intent.FLAG_RECEIVER_FOREGROUND);
            }
            mService.broadcastIntentLocked(null, null, intent,
                    null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                    null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);

            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
            if (mService.canShowErrorDialogs() || showBackground) {
                dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
                proc.anrDialog = dialogToShow;
            } else {
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                        AppNotRespondingDialog.CANT_SHOW);
                // Just kill the app if there is no dialog to be shown.
                mService.killAppAtUsersRequest(proc, null);
            }
        }
        // If we've created a crash dialog, show it without the lock held
        if (dialogToShow != null) {
            dialogToShow.show();
        }
    }

...

Однако, ANR начинается не здесь. Как я и говорила выше, одна из первых причин возникновения этой ошибки — это задержка входного события, которая составляет 5 секунд. Недолгим поиском мы можем найти где задается это значение.

namespace android {
// Default input dispatching timeout if there is no focused application or paused window
// from which to determine an appropriate dispatching timeout.
const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec

Теперь мы можем посмотреть в коде, где вызывается нативная часть. Это происходит в классе InputManagerService.

    // Native callback.
    private long notifyANR(InputApplicationHandle inputApplicationHandle,
            InputWindowHandle inputWindowHandle, String reason) {
        return mWindowManagerCallbacks.notifyANR(
                inputApplicationHandle, inputWindowHandle, reason);
    }

А вот и mWindowManagerCallbacks в InputMonitor:

        if (appWindowToken != null && appWindowToken.appToken != null) {
            // Notify the activity manager about the timeout and let it decide whether
            // to abort dispatching or keep waiting.
            final AppWindowContainerController controller = appWindowToken.getController();
            final boolean abort = controller != null
                    && controller.keyDispatchingTimedOut(reason,
                            (windowState != null) ? windowState.mSession.mPid : -1);
            if (!abort) {
                // The activity manager declined to abort dispatching.
                // Wait a bit longer and timeout again later.
                return appWindowToken.mInputDispatchingTimeoutNanos;
            }
        } else if (windowState != null) {
            try {
                // Notify the activity manager about the timeout and let it decide whether
                // to abort dispatching or keep waiting.
                long timeout = ActivityManager.getService().inputDispatchingTimedOut(
                        windowState.mSession.mPid, aboveSystem, reason);
                if (timeout >= 0) {
                    // The activity manager declined to abort dispatching.
                    // Wait a bit longer and timeout again later.
                    return timeout * 1000000L; // nanoseconds
                }
            } catch (RemoteException ex) {
            }
        }
        return 0; // abort dispatching
    }

Давайте посмотрим внимательнее на inputDispatchingTimedOut(). Тут как раз мы и показываем сообщение через ActivityManager об истечении времени ожидания и даем пользователю решить, следует ли отменить действие или продолжить ожидание. И именно в ActivityManagerService и вызывается AppErrors в случае возникновения crash или ANR.

  private boolean makeAppCrashingLocked(ProcessRecord app,
            String shortMsg, String longMsg, String stackTrace) {
        app.crashing = true;
        app.crashingReport = generateProcessError(app,
                ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
        startAppProblemLocked(app);
        app.stopFreezingAllLocked();
        return handleAppCrashLocked(app, shortMsg, longMsg, stackTrace);
    }
    private void makeAppNotRespondingLocked(ProcessRecord app,
            String activity, String shortMsg, String longMsg) {
        app.notResponding = true;
        app.notRespondingReport = generateProcessError(app,
                ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
                activity, shortMsg, longMsg, null);
        startAppProblemLocked(app);
        app.stopFreezingAllLocked();
    }

Основные причины ANR

  • Блокировка ввода/вывода
  • Перегрузка сети
  • Блокировка потоков
  • Бесконечный цикл
  • Бизнес-логика выполняется слишком долго

Как избежать ANR

  • Главный поток пользовательского интерфейса выполняет логику, связанную только с пользовательским интерфейсом;
  • Сложные вычисления (например, операции с базой данных, операции ввода-вывода, сетевые операции и т.д.) производятся в отдельном потоке;
  • Используйте Handler для взаимодействия между потоком пользовательского интерфейса и рабочим потоком;
  • Используйте RxJava и т.д. для обработки асинхронных операций.

Как поймать ANR

  • Информация об ANR может храниться в файле /data/anr/traces.txt, либо по другому пути /data/anr/anr_*. Получить ее можно с помощью следующих команд:
    adb root
    adb shell ls /data/anr
    adb pull /data/anr/<filename>
  • Использовать проект с открытым исходным кодом ANR-WatchDog для обнаружения ANR
  • См. Как избежать ANR :)

P.S. Все подборки я публикую в телеграм канале @paradisecurity.

ANR stands for Application Not Responding. An ANR will occur if you’re running a process on the UI thread which takes an extended time, usually around 5 seconds. During this point, the GUI (Graphical User Interface) will lock up which can end in anything the user presses won’t be actioned. After the 5 seconds approx. has occurred, if the thread still hasn’t recovered then an ANR dialogue box is shown informing the user that the appliance isn’t responding and can give the user the choice to either wait, in the hope that the app will eventually recover, or to force close the app. This is how the ANR dialog displayed to the user.

ANR dialog displayed to the user

A crash is when an exception within the app has been thrown which has not been handled. For example, if you are trying to set the text of an EditText component, but the EditText is null and there’s no try-catch statement to catch the exception then your app will crash and can be force closed. The user won’t see what caused the crash, they’re going to be shown a dialogue telling that the app has force closed unexpectedly and can give them the choice to send a bug report. For example, an error caused by java.lang.NullPointerException is an ANR. An ANR happens when some long operation takes place in the “main” thread. This is the event loop thread, and if it’s busy, Android cannot process any longer GUI events within the application, and thus presents an ANR dialog. Now, within the trace you posted, most thread seems to be doing fine, there’s no problem. It is idling within the MessageQueue, expecting another message to return. In your case, the ANR was likely a longer operation, rather than something that blocked the thread permanently, so the event thread recovered after the operation finished, and your trace went through after the ANR.

How to prevent an ANR?

Stop doing heavy tasks on the main thread. Instead use worker threads such as IntentService, AsyncTask Handler, or another Thread simply. Detecting where ANRs happen is straightforward if it’s a permanent block (deadlock acquiring some locks for instance), but harder if it’s just a short-lived delay. First, re-evaluate your code and appearance for vulnerable spots and long-running operations. Examples may include using sockets, locks, thread sleeps, and other blocking operations from within the event thread. You should make sure these all happen in separate threads. If nothing seems the matter, use DDMS and enable the thread view. This shows all the threads in your application similar to the trace you have. Reproduce the ANR, and refresh the most thread at an equivalent time. That should show you exactly what’s happening at the time of the ANR. An ANR is going to be triggered for your app when one among the subsequent conditions occur:

  1. While your activity is within the foreground, your app has not fed with an input event or BroadcastReceiver (such as key press or screen touch events) within 5 seconds.
  2. While you aren’t doing an activity within the foreground, your BroadcastReceiver hasn’t finished executing within a substantial amount of your time.

If your app is experiencing ANRs, you’ll use the guidance during this article to diagnose and fix the matter.

Android vitals

Android vitals can help improve your app’s performance by alerting you, via the Play Console, when your app is exhibiting excessive ANRs. Android vitals considers ANRs excessive when an app:

  1. Exhibits a minimum of one ANR in a minimum of 0.47% of its daily sessions.
  2. Exhibits 2 or more ANRs in a minimum of 0.24% of its daily sessions.
  3. Exhibits 3 or more ANRs in a minimum of 0.17% of its daily sessions.
  4. Exhibits 3 or more ANRs in a minimum of 0.14% of its daily sessions.

Diagnosing ANRs

The ANRs could be solved easily as the Android Interface Provide Efficient Tools to remove them! Finding them may include (but are not limited to):

  1. The app is doing slow operations which involves the I/O operation of the operating system.
  2. The main thread is doing a synchronous binder call to a different process, which another process is taking an extended time to return.
  3. The main thread is during a deadlock with another thread, either in your process or via a binder call. the most thread isn’t just expecting an extended operation to end but is during a deadlock situation.
  4. The app is doing an extended calculation on the basic thread.

Using the Android Strict Mode (API Level > 9)

Starting API Level 9 using StrictMode will help you discover certain accidental I/O operations on the most thread while you’re developing your app. you’ll use StrictMode at the appliance or activity level. Read more about how to use StrictMode here.

Moreover, you can also find about the ANRs by pulling a Traces File from Android ADB as Follows:

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

But if your users are still experiencing ANRs, you are bound to check out the status of the prime a.k.a. main thread in Android Device Monitor. Usually, the main thread is in the RUNNABLE state if it’s ready to update the UI and is generally responsive if everything is fine!

An Example

Java

@Override

public void onClick(View view) {

    MergeSort.sort(data);

}

In the above-mentioned case what we need to do is to remove the sorting process from the main thread and place it into another class or thread, so that the system can handle it asynchronously.

A Tip

When an ANR occurs and your app crashes out of nowhere, Android Studio logs some info related to the case in a text file on the device itself. You can use ADB to gather logs and have a look. You can also add Crashlytics from Firebase to catch hold of ANRs when they occur in your app, and get their frequency, and event the activity thread on which it happened! View More Details about ANR by visiting Here.

Last Updated :
06 Feb, 2023

Like Article

Save Article

Приложение отвечает: как мы уменьшили количество ANR-ошибок в шесть раз. Часть 1, про сбор данных +12

Разработка под Android, Тестирование мобильных приложений, Аналитика мобильных приложений, Блог компании Badoo, Google API


Рекомендация: подборка платных и бесплатных курсов 3D-моделирования — https://katalog-kursov.ru/

Пожалуй, одна из худших проблем, которая может случиться с вашим приложением, — ошибка ANR (Application Not Responding), когда приложение не отвечает. Если таких ошибок много, они могут негативно влиять не только на пользовательский опыт, но и на позицию в выдаче Google Play и фичеринг. 

В начале прошлого года количество ANRs в приложении Badoo превышало порог “Bad Behaviour” в Google Play. Поэтому мы собрали команду для решения этой проблемы и потратили несколько месяцев, экспериментируя с разными подходами. В результате мы смогли уменьшить количество таких ошибок более чем в шесть раз.

В этой серии из двух статей я расскажу о том, как нам это удалось, что дало наибольший эффект и как вы можете использовать эти подходы в своём приложении.

В первой части мы поговорим об основах: что представляет собой ошибка ANR и как её лучше отслеживать. Если вы уже знакомы с этой темой, предлагаю перейти ко второй части, в которой я расскажу о наших способах решения этой проблемы.

Что такое ошибка ANR?

Обычно любое приложение с графическим интерфейсом выполняет все связанные с ним операции и отрисовку в отдельном UI-потоке исполнения. Android не исключение: здесь в главном потоке приложения выполняется цикл, отвечающий за все действия с интерфейсом:

При использовании этого цикла крайне важно не выполнять длительные операции, потому что это напрямую повлияет на отзывчивость приложения. Если в главном потоке выполнять слишком много действий, это может привести к снижению частоты кадров или даже к зависаниям интерфейса:

Чтобы как-то идентифицировать такие ситуации, в Android ввели понятие ANR, с помощью которого система сообщает, что приложение зависло. Вот что об этом говорится в официальной документации:

Когда UI-поток Android-приложения блокируется слишком долго, выдаётся ошибка Application Not Responding (ANR).

ANR выдаётся, когда приложение находится в одном из этих состояний:

— на переднем плане находится Activity, приложение в течение пяти секунд не отвечает на входящие события или BroadcastReceiver, например нажатия на кнопки или касания экрана;

— на переднем плане нет Activity, ваш BroadcastReceiver не закончил исполнение в течение длительного времени.

Если ANR случается, когда на переднем плане находится Activity вашего приложения, Android показывает диалоговое окно с предложением закрыть приложение или подождать.

Довольно легко принудительно вызвать ANR, написав Thread.sleep() в любом обработчике интерфейса, например обработчик нажатия кнопки. После нажатия на кнопку вы увидите примерно следующее:

Наличие ошибок ANR в вашем приложении не только влияет на опыт его использования, но и, согласно документации Google, может повлиять на позицию в поисковой выдаче и продвижение в Google Play.

Чтобы снизить вероятность возникновения ANR, нужно всего лишь избегать выполнения длительных операций в главном потоке. Звучит вроде бы просто, но иногда не так легко определить корневую проблему, которая приводит к таким ошибкам. Поэтому довольно важно иметь хорошую систему мониторинга и репортинга ANR-ошибок.

Давайте посмотрим, какие существуют способы отладки ANR-ошибок и какие инструменты могут быть в этом полезны.

Отслеживание ANR

Локальный анализ

Самый простой случай — если у вас есть возможность стабильно воспроизводить ANR-проблему локально. Существует довольно много инструментов, которые могут помочь вам быстро найти источник проблемы.

Первое, что можно сделать, — это проверить дамп стек-трейсов для всех потоков (thread dump). Когда приложение перестает отвечать, Android создаёт дамп всех текущих потоков, который может помочь в анализе проблемы. Обычно он находится в директории /data/anr/, точный путь можно найти в Logcat сразу после сообщения об ошибке ANR.

Дамп потоков содержит стек-трейсы: вы увидите, в каком состоянии был каждый поток (например, какая строка выполнялась в конкретный момент времени). По сути, это состояние приложения на момент создания дампа.

Чаще всего причина возникновения ANR обнаруживается в стек-трейсе главного потока скорее всего, код в этом месте выполняется слишком долго. Если информации из этого стек-трейса будет недостаточно, можно попробовать обратиться к довольно неплохой документации от Google, где описываются основные причины, способы диагностирования и решения проблемы ANR.

Отслеживание с помощью Google Play

Google Play автоматически отправляет отчёты об ошибках ANR, если у пользователя включена такая опция. В консоли Google Play есть несколько метрик и инструментов для анализа ANR.

Во-первых, можно увидеть агрегированные графики с общим количеством ANR-ошибок за день. Также есть такая метрика, как ANR rate — отношение количества сессий за день, в которых возникала хотя бы одна ANR-ошибка, к общему количеству сессий за сутки. Для этой метрики задан порог в 0,47%, превышение которого считается «неудовлетворительным поведением» (“Bad Behaviour”) и может плохо повлиять на позицию приложения в Google Play. 

Во-вторых, можно открывать отдельные отчёты об ANR-ошибках, сгруппированные по схожести на основе стек-трейса. Основные группы находятся в разделе Android Vitals. И это, вероятно, наиболее полезный раздел для выявления самых частых причин возникновения ANR-ошибок в вашем приложении.

Если вы активно используете консоль Google Play, вы могли заметить некоторые её недостатки. Например, к отчётам нельзя прикрепить дополнительную информацию, такую как логи для отладки. Также невозможно настроить логику группировки отчётов. Иногда система помещает в одну группу ошибки, возникшие по разным причинам, а иногда раскидывает по разным группам ошибки, у которых причина одна.

Всё это иногда затрудняет определение основных ошибок и поиск изначальных проблем. Что же можно сделать для улучшения ситуации?

Скачивание данных из Google Play

Для решения проблемы с логикой группировки можно попробовать скачать сырые отчёты об ANR-ошибках из Google Play для последующего ручного анализа. Раньше была возможность выгрузить эти данные из Google Cloud Storage, но несколько лет назад Google перестала поддерживать этот функционал:

Однако всё ещё можно просматривать отдельные отчёты в консоли. Но как нам экспортировать тысячи отчётов, не потратив при этом кучу времени на рутинную работу?

Существует много способов автоматизировать сбор информации с сайтов. Самый правильный и простой — получение данных через API, но, к сожалению, Google не предоставляет публичный API для получения отчётов. Одно из решений — эмулировать пользовательское поведение, автоматически кликая на ссылки и кнопки в браузере и сохраняя отображающийся текст.

Веб-скрапер можно реализовать с помощью популярного инструмента Selenium, который предоставляет простой интерфейс для взаимодействия с веб-страницами. Изначально он предназначался для создания автоматизированных тестов для веб-приложений и доступен на разных языках, включая Java и Kotlin.

Мы реализовали скрапер на Selenium и получили сырые отчёты об ANR-ошибках для одного из релизов. Благодаря этому нам удалось проанализировать их так, как не получилось бы сделать с помощью встроенных в консоль Google Play инструментов. Например, просто поискав в отчётах по ключевым словам “Application.onCreate”, мы обнаружили, что около 60% ошибок произошло во время выполнения метода Application.onCreate. При этом в консоли Google Play нет возможности получить такую информацию, так как отчёты разбиты по группам.

Внутренняя аналитика

Другой способ сбора дополнительных данных и проведения расширенного анализа заключается в настройке собственного репортинга ANR-ошибок. В прошлом мы уже экспериментировали с решением похожих проблем, настраивая репортинг крашей. Для того чтобы проводить анализ падений приложения, мы создали внутренний инструмент Gelato.

Его функциональность схожа с возможностями других инструментов для краш-репортинга, таких как Firebase Crashlytics и App Center, но ещё и позволяет нам полностью контролировать сохраняемые данные, менять логику группировки и применять сложную фильтрацию:

Это не реальные данные приложения Bumble, иллюстрация сделана просто для примера

Это не реальные данные приложения Bumble, иллюстрация сделана просто для примера

Мы решили отслеживать в Gelato ещё и ANR-ошибки в надежде, что это поможет нам в поиске их причин. Для этого нам нужно было знать, когда приложение перестаёт отвечать. В Android 11 появился новый API, предоставляющий информацию о недавних причинах завершения процесса, но у большинства наших пользователей установлены более ранние версии ОС, поэтому нам требовалось найти другое решение.

И мы нашли простой способ, который часто используется для отслеживания зависаний главного потока исполнения: запустить watchdog-поток, который периодически будет пытаться выполнить задачу в главном потоке. Если задача не выполняется за определённый промежуток времени, то можно сохранить дамп текущего состояния потоков и отправить его в наш инструмент для анализа отчётов о падениях:

Такую логику реализует, например, библиотека, которой мы воспользовались для реализации репортинга в Gelato. Это позволило нам проводить более глубокий анализ данных и лучше интегрировать этот инструмент в нашу инфраструктуру. Например, теперь мы можем сравнивать зависания главного потока в разных вариантах в ходе A/B-тестирования.

Вот пример отчёта в нашей системе:

Это не реальные данные приложения Bumble, иллюстрация сделана просто для примера

Это не реальные данные приложения Bumble, иллюстрация сделана просто для примера

Полезный совет: собирайте и отправляйте вместе с отчётом лог событий аналитики. Иногда это даёт возможность буквально пошагово воспроизвести проблему. 

Если у вас нет своего решения для сбора отчётов о падениях приложения, вы можете настроить репортинг и в сторонние инструменты. Например, можно отправлять ANR-ошибки в App Center или Firebase Crashlytics, так как они предоставляют API для отправки кастомных крашей.

Но помните, что все эти отчёты нельзя считать полной альтернативой ANR-отчётам в Google Play (как мы говорили выше, в Android немного другие правила определения таких ошибок). Но в любом случае это может помочь получить общее представление об основных проблемах. Вполне вероятно, что если генерируется много отчётов о зависании главного потока исполнения в какой-то части вашего приложения, то в ней происходят и ANR-ошибки. 

В завершение

Мы обсудили, что представляют собой ANR-ошибки и как их можно отслеживать. Во второй части статьи я расскажу о наших подходах к снижению ANR rate и о том, что из этого получилось.

Ссылки

  1. Android Vitals в Google Play

  2. Отладка ANR

  3. API для получения причин завершения процесса

  4. Фреймворк для тестирования веб-страниц

  5. Библиотека для определения зависаний

Пожалуй, одна из худших проблем, которая может случиться с вашим приложением, — ошибка ANR (Application Not Responding), когда приложение не отвечает. Если таких ошибок много, они могут негативно влиять не только на пользовательский опыт, но и на позицию в выдаче Google Play и фичеринг. 

В начале прошлого года количество ANRs в приложении Badoo превышало порог “Bad Behaviour” в Google Play. Поэтому мы собрали команду для решения этой проблемы и потратили несколько месяцев, экспериментируя с разными подходами. В результате мы смогли уменьшить количество таких ошибок более чем в шесть раз.

В этой серии из двух статей я расскажу о том, как нам это удалось, что дало наибольший эффект и как вы можете использовать эти подходы в своём приложении.

В первой части мы поговорим об основах: что представляет собой ошибка ANR и как её лучше отслеживать. Если вы уже знакомы с этой темой, предлагаю подождать выхода второй части, в которой я расскажу о наших способах решения этой проблемы.

Что такое ошибка ANR?

Обычно любое приложение с графическим интерфейсом выполняет все связанные с ним операции и отрисовку в отдельном UI-потоке исполнения. Android не исключение: здесь в главном потоке приложения выполняется цикл, отвечающий за все действия с интерфейсом:

При использовании этого цикла крайне важно не выполнять длительные операции, потому что это напрямую повлияет на отзывчивость приложения. Если в главном потоке выполнять слишком много действий, это может привести к снижению частоты кадров или даже к зависаниям интерфейса:

Чтобы как-то идентифицировать такие ситуации, в Android ввели понятие ANR, с помощью которого система сообщает, что приложение зависло. Вот что об этом говорится в официальной документации:

Когда UI-поток Android-приложения блокируется слишком долго, выдаётся ошибка Application Not Responding (ANR).

ANR выдаётся, когда приложение находится в одном из этих состояний:

— на переднем плане находится Activity, приложение в течение пяти секунд не отвечает на входящие события или BroadcastReceiver, например нажатия на кнопки или касания экрана;

— на переднем плане нет Activity, ваш BroadcastReceiver не закончил исполнение в течение длительного времени.

Если ANR случается, когда на переднем плане находится Activity вашего приложения, Android показывает диалоговое окно с предложением закрыть приложение или подождать.

Довольно легко принудительно вызвать ANR, написав Thread.sleep() в любом обработчике интерфейса, например обработчик нажатия кнопки. После нажатия на кнопку вы увидите примерно следующее:

Наличие ошибок ANR в вашем приложении не только влияет на опыт его использования, но и, согласно документации Google, может повлиять на позицию в поисковой выдаче и продвижение в Google Play.

Чтобы снизить вероятность возникновения ANR, нужно всего лишь избегать выполнения длительных операций в главном потоке. Звучит вроде бы просто, но иногда не так легко определить корневую проблему, которая приводит к таким ошибкам. Поэтому довольно важно иметь хорошую систему мониторинга и репортинга ANR-ошибок.

Давайте посмотрим, какие существуют способы отладки ANR-ошибок и какие инструменты могут быть в этом полезны.

Отслеживание ANR

Локальный анализ

Самый простой случай — если у вас есть возможность стабильно воспроизводить ANR-проблему локально. Существует довольно много инструментов, которые могут помочь вам быстро найти источник проблемы.

Первое, что можно сделать, — это проверить дамп стек-трейсов для всех потоков (thread dump). Когда приложение перестает отвечать, Android создаёт дамп всех текущих потоков, который может помочь в анализе проблемы. Обычно он находится в директории /data/anr/, точный путь можно найти в Logcat сразу после сообщения об ошибке ANR.

Дамп потоков содержит стек-трейсы: вы увидите, в каком состоянии был каждый поток (например, какая строка выполнялась в конкретный момент времени). По сути, это состояние приложения на момент создания дампа.

Чаще всего причина возникновения ANR обнаруживается в стек-трейсе главного потока скорее всего, код в этом месте выполняется слишком долго. Если информации из этого стек-трейса будет недостаточно, можно попробовать обратиться к довольно неплохой документации от Google, где описываются основные причины, способы диагностирования и решения проблемы ANR.

Отслеживание с помощью Google Play

Google Play автоматически отправляет отчёты об ошибках ANR, если у пользователя включена такая опция. В консоли Google Play есть несколько метрик и инструментов для анализа ANR.

Во-первых, можно увидеть агрегированные графики с общим количеством ANR-ошибок за день. Также есть такая метрика, как ANR rate — отношение количества сессий за день, в которых возникала хотя бы одна ANR-ошибка, к общему количеству сессий за сутки. Для этой метрики задан порог в 0,47%, превышение которого считается «неудовлетворительным поведением» (“Bad Behaviour”) и может плохо повлиять на позицию приложения в Google Play. 

Во-вторых, можно открывать отдельные отчёты об ANR-ошибках, сгруппированные по схожести на основе стек-трейса. Основные группы находятся в разделе Android Vitals. И это, вероятно, наиболее полезный раздел для выявления самых частых причин возникновения ANR-ошибок в вашем приложении.

Если вы активно используете консоль Google Play, вы могли заметить некоторые недостатки. Например, к отчётам нельзя прикрепить дополнительную информацию, такую как логи для отладки. Также невозможно настроить логику группировки отчётов. Иногда система помещает в одну группу ошибки, возникшие по разным причинам, а иногда раскидывает по разным группам ошибки, у которых причина одна.

Всё это иногда затрудняет определение основных ошибок и поиск изначальных проблем. Что же можно сделать для улучшения ситуации?

Скачивание данных из Google Play

Для решения проблемы с логикой группировки можно попробовать скачать сырые отчёты об ANR-ошибках из Google Play для последующего ручного анализа. Раньше была возможность выгрузить эти данные из Google Cloud Storage, но несколько лет назад Google перестала поддерживать этот функционал:

Однако всё ещё можно просматривать отдельные отчёты в консоли. Но как нам экспортировать тысячи отчётов, не потратив при этом кучу времени на рутинную работу?

Существует много способов автоматизировать сбор информации с сайтов. Самый правильный и простой — получение данных через API, но, к сожалению, Google не предоставляет публичный API для получения отчётов. Одно из решений — эмулировать пользовательское поведение, автоматически кликая на ссылки и кнопки в браузере и сохраняя отображающийся текст.

Веб-скрапер можно реализовать с помощью популярного инструмента Selenium, который предоставляет простой интерфейс для взаимодействия с веб-страницами. Изначально он предназначался для создания автоматизированных тестов для веб-приложений и доступен на разных языках, включая Java и Kotlin.

Мы реализовали скрапер на Selenium и получили сырые отчёты об ANR-ошибках для одного из релизов. Благодаря этому нам удалось проанализировать их так, как не получилось бы сделать с помощью встроенных в консоль Google Play инструментов. Например, просто поискав в отчётах по ключевым словам “Application.onCreate”, мы обнаружили, что около 60% ошибок произошло во время выполнения метода Application.onCreate. При этом в консоли Google Play нет возможности получить такую информацию, так как отчёты разбиты по группам.

Внутренняя аналитика

Другой способ сбора дополнительных данных и проведения расширенного анализа заключается в настройке собственного репортинга ANR-ошибок. В прошлом мы уже экспериментировали с решением похожих проблем, настраивая репортинг крашей. Для того чтобы проводить анализ падений приложения, мы создали внутренний инструмент Gelato.

Его функциональность схожа с возможностями других инструментов для краш-репортинга, таких как Firebase Crashlytics и App Center, но ещё и позволяет нам полностью контролировать сохраняемые данные, менять логику группировки и применять сложную фильтрацию:

Это не реальные данные приложения Bumble, иллюстрация сделана просто для примера

Это не реальные данные приложения Bumble, иллюстрация сделана просто для примера

Мы решили отслеживать в Gelato ещё и ANR-ошибки в надежде, что это поможет нам в поиске их причин. Для этого нам нужно было знать, когда приложение перестаёт отвечать. В Android 11 появился новый API, предоставляющий информацию о недавних причинах завершения процесса, но у большинства наших пользователей установлены более ранние версии ОС, поэтому нам требовалось найти другое решение.

И мы нашли простой способ, который часто используется для отслеживания зависаний главного потока исполнения: запустить watchdog-поток, который периодически будет пытаться выполнить задачу в главном потоке. Если задача не выполняется за определённый промежуток времени, то можно сохранить дамп текущего состояния потоков и отправить его в наш инструмент для анализа отчётов о падениях:

Такую логику реализует, например, библиотека, которой мы воспользовались для реализации репортинга в Gelato. Это позволило нам проводить более глубокий анализ данных и лучше интегрировать этот инструмент в нашу инфраструктуру. Например, теперь мы можем сравнивать зависания главного потока в разных вариантах в ходе A/B-тестирования.

Вот пример отчёта в нашей системе:

Это не реальные данные приложения Bumble, иллюстрация сделана просто для примера

Это не реальные данные приложения Bumble, иллюстрация сделана просто для примера

Полезный совет: собирайте и отправляйте вместе с отчётом лог событий аналитики. Иногда это даёт возможность буквально пошагово воспроизвести проблему. 

Если у вас нет своего решения для сбора отчётов о падениях приложения, вы можете настроить репортинг и в сторонние инструменты. Например, можно отправлять ANR-ошибки в App Center или Firebase Crashlytics, так как они предоставляют API для отправки кастомных крашей.

Но помните, что все эти отчёты нельзя считать полной альтернативой ANR-отчётам в Google Play (как мы говорили выше, в Android немного другие правила определения таких ошибок). Но в любом случае это может помочь получить общее представление об основных проблемах. Вполне вероятно, что если генерируется много отчётов о зависании главного потока исполнения в какой-то части вашего приложения, то в ней происходят и ANR-ошибки. 

В завершение

Мы обсудили, что представляют собой ANR-ошибки и как их можно отслеживать. Во второй части статьи я расскажу о наших подходах к снижению ANR rate и о том, что из этого получилось.

Ссылки

  1. Android Vitals в Google Play: https://developer.android.com/distribute/best-practices/develop/android-vitals

  2. Отладка ANR: https://developer.android.com/topic/performance/vitals/anr

  3. API для получения причин завершения процесса: https://developer.android.com/reference/kotlin/android/app/ActivityManager#gethistoricalprocessexitreasons

  4. Фреймворк для тестирования веб-страниц: https://www.selenium.dev/

  5. Библиотека для определения зависаний: https://github.com/SalomonBrys/ANR-WatchDog

На чтение 2 мин. Просмотров 136 Опубликовано

ANR или Приложение не отвечает — это ошибка Android, которая возникает, когда поток пользовательского интерфейса перестает отвечать на запросы пользователя. Когда приложение перестает отвечать на запросы, пользователю предоставляется диалоговое окно ANR , которое дает ему возможность принудительно закрыть приложение.

Содержание

  1. Что вызывает ANR?
  2. Распространенные виновники
  3. Методы диагностики
  4. Использовать строгий режим
  5. Включить фоновые диалоги ANR в параметрах разработчика
  6. Проверяйте файлы трассировки с помощью adb

Что вызывает ANR?

  1. Если ваше приложение не отвечает на ввод пользователя или BroadcastReceiver в течение пяти секунд.

  2. Ваш BroadcastReceiver не завершил выполнение в течение значительного промежутка времени, и в приложении нет текущей задачи переднего плана.

задача переднего плана — это задача, заметная пользователю. Примером текущей задачи переднего плана является музыкальное приложение, воспроизводящее звук. Эти задачи отображают уведомление для пользователя.

** BroadcastReceiver — это компонент, который прослушивает общесистемные трансляции. например, трансляция с сообщением об отключении экрана.

Распространенные виновники

Обычно ошибки ANR срабатывают, потому что ваше приложение выполняет следующие действия:

  1. Медленные операции с I/ O в основном потоке.
  2. Выполнение длительных вычислений в основном потоке.
  3. Выполнение синхронного вызова связывателя в основном потоке, а другой процесс требует времени, чтобы ответить .
  4. Ожидание в основном потоке другого потока, выполняющего длительную операцию.
  5. Застрял в тупиковой ситуации. Взаимоблокировки могут возникать в основном потоке, когда он ожидает ресурсов, которые не были освобождены другим процессом, поэтому он не может получить необходимые ему ресурсы. Эти другие процессы могут быть в другом потоке, вашем процессе или в вызове связывателя.

Методы диагностики

Использовать строгий режим

С помощью StrictMode вы можете обнаруживать случайные операции ввода-вывода.

Подробнее о StrictMode в официальной документации.

Включить фоновые диалоги ANR в параметрах разработчика

Не все ANR видны пользователю; следовательно, приложение может столкнуться с проблемами производительности без ведома пользователя. Включите фоновые диалоги ANR в параметрах разработчика .

Проверяйте файлы трассировки с помощью adb

Файлы трассировки создаются в событии ANR. Вы можете получить эти файлы, используя Android Debug Bridge (adb) как root, используя следующие команды:

  adb rootadb shell ls/data/anradb pull/data/anr/  

Прочтите полную документацию по Android для ANR здесь.

What is ANR (App Not Responding)?

If you’ve ever experienced your Android device freezing up or becoming unresponsive, you’ve likely encountered an ANR. ANRs occur when the main thread of an Android app is blocked for too long. In this article, we’ll discuss what ANRs are and how to solve them.

If you’ve ever experienced your Android device freezing up or becoming unresponsive, you’ve likely encountered an ANR. ANRs occur when the main thread of an app is blocked for more than a few seconds. This can happen when the app is doing too much work on the main thread, such as processing data or drawing views.

Read about What Is The Difference Between Notifications And Push Notifications

ANRs can also occur when the app is waiting for a response from another process, such as a server. When an ANR occurs, the system will usually display a dialog to the user asking if they want to wait or force close the app.

There are a few ways to detect ANRs in your app. The first is to look for stack traces in your logs that indicate that the main thread was blocked for a long time. The second way is to use the ANR (Application Not Responding) dialog. This is the easiest way to detect ANRs because it happens automatically when an ANR occurs.

What are ANRs?

ANRs, or Android Not Responding errors, are a frustrating experience for any Android user. They can happen when you’re using an app, or even just when your phone is idle. ANRs can be caused by a number of things, but the most common cause is a lack of response from an app.

There are a few things you can do to try and fix an ANR. First, you can try restarting your device. If that doesn’t work, you can try clearing the cache for the offending app. If that still doesn’t work, you can try disabling ANR monitoring in Android Auto. Finally, if all else fails, you can always factory reset your device.

What causes ANRs?

An application not responding (ANR) error is a frustrating experience for Android users. When an app freezes or becomes unresponsive, ANRerrors pop up. This article will explain what ANRs are and how to debug them.

ANRs happen when an app is either frozen or unresponsive. If an app is taking too long to do something, the system will kill it and show an ANR error. This can happen if the app is doing too much work on the main thread, which is the thread that handles UI updates. It can also happen if the app is waiting for a response from another process, like a network call.

To debug ANRs, you need to be able to reproduce them first. Once you’ve reproduced the ANR, take a look at your logs to see what was happening when the ANR occurred.

How to detect ANRs?

An ANR, or Android Not Responding, error is a frustrating issue that can plague Android users. Here’s how to detect and debug ANRs so you can fix the issue.

ANRs occur when an app stops responding to input for a period of time. This can happen for a number of reasons, but the most common cause is an unresponsive UI thread.

There are a few ways to detect ANRs. First, check your device’s logcat output for any stack traces that mention “ANR.” You can also use the Android Debug Bridge (ADB) to generate a stack trace if you’re experiencing an ANR on your device.

Once you’ve detected an ANR, it’s time to debug the issue. The first step is to identify the offending thread.

How to prevent ANRs?

ANRs are Android’s way of telling you that something’s wrong with your app. They can be caused by a number of things, but the most common cause is when your app is taking too long to do something.

There are a few things you can do to prevent ANRs from happening in your app. First, make sure you’re not doing too much work on the main thread. Second, use AsyncTask or other background threads to do long-running operations. Finally, if you must do work on the main thread, use HandlerThreads to schedule that work.

If you do get an ANR, don’t panic! There are a few things you can do to debug it. First, take a look at the stack trace to see what your app was doing when the ANR happened.

An Application Not Responding (ANR) error is a frustrating issue for Android users. ANRs occur when an app fails to respond to an input event within a certain amount of time. This can happen when the app is doing too much work on the main thread, causing it to miss processing the input event. ANRs can be caused by many different things, but they all result in the same problem: an unresponsive app.

There are a few ways to detect ANRs. The first is through logcat output. If you see an ANR in your logcat output, it will usually include information about what caused the ANR. The second way to detect ANRs is throught he Android Debug Bridge (ADB). You can use ADB to connect to a device and run a number of commands, one of which is “dumpsys window policy”.

What is anr in android?

An ANR is an Android Not Responding message that appears when the system detects that an app has been unresponsive for a period of time. The ANR dialog gives the user the option to wait or force close the app.

ANRs usually occur when an app is doing too much work on the main thread, causing it to become unresponsive. When this happens, the system will kill the app and display the ANR dialog.

What is anr responding time in android?

ANR is short for “Application Not Responding”. It is a dialog that appears when an Android app does not respond to an input event within a certain amount of time. This can happen when the app is doing too much work on the main thread, such as downloading data from the internet or processing large amounts of data.

There are two ways to solve ANRs: using a background thread, or using Firebase’s Crashlytics tool.

Background threads are used to offload work from the main thread. This means that the app can continue to respond to input events while the background thread is working. To use a background thread, you need to create a new Thread object and pass it a Runnable object. The Runnable object contains the code that will be executed on the background thread.

What is anr responding time in android?

ANR stands for “Application Not Responding”. It is a popup error message that appears when an app does not respond to user input in a timely manner.

There are two types of ANRs: soft ANRs and hard ANRs. Soft ANRs happen when an app is taking too long to process an action, but it is still responding to system broadcasts. Hard ANRs happen when an app is unresponsive for a period of time, and the system determines that the app has frozen.

ANRs can be caused by many things, but the most common cause is when an app is performing a long-running operation on the main thread. This can happen when an app is doing too much work on the main thread, or when it is waiting for a slow network operation to complete.

Android anr causes?

An application not responding (ANR) error is a frustrating experience for any Android user. This error can occur for a number of reasons, but the most common cause is when an app is waiting for a response from another app or process. There are a few ways to solve this problem, but the most effective way is to use the Android Debug Bridge (ADB). ADB is a powerful tool that allows developers to debug their apps in real time. By using ADB, you can see what processes are causing the ANR and then fix the problem.

Why anr comes in android?

An Application Not Responding (ANR) error is a frustrating experience for any Android user. ANRs often occur when an app is performing a long-running operation, such as downloading a large file or processing a lot of data. When an ANR occurs, the app becomes unresponsive and the Android system displays a dialog box to let the user know that the app is not responding.

There are several ways to detect ANRs in Android. One way is to use the “adb logcat” command-line tool. This tool lets you view the system logs on your device, which can be helpful for debugging ANR issues. Another way to detect ANRs is to use a third-party app like “ANR Detector.” This app monitors your device for ANR activity and sends you a notification if an ANR occurs.

How to solve anr in android?

ANRs, or Android Not Responding errors, are one of the most frustrating things that can happen when you’re using your smartphone. They usually happen when you’re doing something that requires a lot of processing power, like playing a game or watching a video.

Fortunately, there are some things you can do to try and fix an ANR. First, make sure you’re running the latest version of Android. Sometimes ANRs are caused by bugs that have already been fixed in newer versions of the operating system.

If updating your phone doesn’t help, try restarting it. If that doesn’t work, try uninstalling any apps that you recently installed. One of them may be causing the problem. If you still can’t fix the problem, your last resort is to factory reset your phone.

How to analyse anr in android?

When your Android app is unresponsive, an ANR is triggered. This stands for “Application Not Responding” and is usually caused by a frozen UI or database locked main thread. If you’re experiencing ANRs, there are some steps you can take to debug and solve the issue.

First, take a look at your code to see if there are any potential deadlocks. If so, try to avoid them by using different synchronization mechanisms. You can also try running your app in a debugger to see where the ANR is occurring.

If you’re still having trouble, you can try increasing the ANR threshold in your system settings. This will give your app more time to respond before an ANR is triggered. However, keep in mind that this may cause other apps to experience ANRs more frequently.

How to generate anr in android?

If you’re developing for Android, you probably know how important it is to have a good generated anr. Anr stands for “Application Not Responding” and is a dreaded error that can lead to crashes and data loss.

So how do you generate a good anr? First, make sure your code is well-organized and free of errors. Second, avoid using too many threads or AsyncTasks.

How to find anr in android?

An ANR, or Android Not Responding, error is a frustrating issue that can occur when using Android devices. This article will explain what an ANR is and how to solve ANR in Android.

ANRs occur when an app is unresponsive for a period of time, typically 5 seconds. This can happen for a number of reasons, but the most common cause is when an app is waiting for a response from the system or another app. When an ANR occurs, the system will automatically kill the unresponsive app and display a dialog to the user.

There are a few things you can do to prevent ANRs from occurring. One is to disable ANR monitoring on your device. To do this, go to Settings > Developer Options and turn off the “ANR Monitoring” option.

Follow me on LinkedIn Hanif Marwat ASO Expert

Понравилась статья? Поделить с друзьями:
  • Ошибки 3011 3012
  • Ошибки alfa romeo 159
  • Ошибки 301 304
  • Ошибки 3 0x80080005 system level
  • Ошибки 2jz gte vvti