Слушайте и отвечайте ANR?

Есть ли способ получить уведомление, когда ваше приложение запускает ANR (приложение не отвечает)? Как и обработчик исключений по умолчанию?

В ожидании ответов "что бы вы сделали с этим", просто регистрировалось. Не "ничего" делать.

Ответ 1

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

Ответ 2

Я об этом немного подумал. Вы могли бы сделать следующее, хотя его довольно тяжело. ANR записывает файл потоков в общедоступный каталог:

/data/anr/traces.txt

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

Я не уверен на 100% формата файла.

Ответ 3

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

  • Скопируйте небольшой код, который будет запущен в потоке пользовательского интерфейса, как можно скорее.
  • Подождите X секунд (вы решите).
  • Посмотрите, запущен ли код: если он есть, вернитесь к 1
  • Если код не был запущен, это означает, что поток пользовательского интерфейса был заблокирован не менее X секунд, вызывает исключение с трассировкой стека потока пользовательского интерфейса.

Я написал небольшую библиотеку, которая делает именно это и которую я использую с ACRA.

Я надеюсь, что это поможет;)

Ответ 4

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

здесь небольшая выборка приложения, вызывающая ANR:

...
findViewById(R.id.button).setOnClickListener(new OnClickListener()
  {
    @Override
    public void onClick(final View v)
      {
      try
        {
        Thread.sleep(10000);
        }
      catch(final InterruptedException e)
        {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }
      }
  });
...

вот журнал, который я получил из logcat, когда я получил ANR:

08-03 13:02:37.746: E/ActivityManager(158): ANR in com.example.anr (com.example.anr/.MainActivity)
08-03 13:02:37.746: E/ActivityManager(158): Reason: keyDispatchingTimedOut
08-03 13:02:37.746: E/ActivityManager(158): Load: 6.19 / 2.37 / 0.86
08-03 13:02:37.746: E/ActivityManager(158): CPU usage from 5598ms to 0ms ago:
08-03 13:02:37.746: E/ActivityManager(158):   2.6% 158/system_server: 2.5% user + 0.1% kernel / faults: 86 minor
08-03 13:02:37.746: E/ActivityManager(158):   0.5% 298/com.android.phone: 0.3% user + 0.1% kernel / faults: 15 minor
08-03 13:02:37.746: E/ActivityManager(158):   0% 35/rild: 0% user + 0% kernel
08-03 13:02:37.746: E/ActivityManager(158): 4.6% TOTAL: 3.9% user + 0.6% kernel
08-03 13:02:37.746: E/ActivityManager(158): CPU usage from 2029ms to 2654ms later:
08-03 13:02:37.746: E/ActivityManager(158):   11% 158/system_server: 4.8% user + 6.4% kernel / faults: 2 minor
08-03 13:02:37.746: E/ActivityManager(158):     11% 192/InputDispatcher: 4.8% user + 6.4% kernel
08-03 13:02:37.746: E/ActivityManager(158):     1.6% 163/Compiler: 1.6% user + 0% kernel
08-03 13:02:37.746: E/ActivityManager(158):     1.6% 193/InputReader: 0% user + 1.6% kernel
08-03 13:02:37.746: E/ActivityManager(158): 18% TOTAL: 9.3% user + 9.3% kernel

Итак, да, я думаю, что это возможно.