Идеальный способ установки глобального обработчика исключенных исключений в Android

Я хочу установить глобальный обработчик исключенных исключений для всех потоков в приложении для Android. Итак, в моем подклассе Application я устанавливаю реализацию Thread.UncaughtExceptionHandler как обработчик по умолчанию для неперехваченных исключений.

 Thread.setDefaultUncaughtExceptionHandler( new DefaultExceptionHandler(this)); 

В моей реализации я пытаюсь отобразить AlertDialog отображая соответствующее сообщение об исключении.

Однако это не работает. Всякий раз, когда создается исключение для любого потока, который не обрабатывается, я получаю запас, диалог по умолчанию ОС («Извините! -Application-has-stop-неожиданный диалог»).

Каков правильный и идеальный способ установки обработчика по умолчанию для неперехваченных исключений?

Solutions Collecting From Web of "Идеальный способ установки глобального обработчика исключенных исключений в Android"

Это должно быть все, что вам нужно. (Убедитесь, что вы заставляете процесс останавливаться после этого – все может быть в неопределенном состоянии.)

Первое, что нужно проверить, – это вызов обработчика Android. Возможно, ваша версия вызывается, но неудачно, и система system_server показывает общий диалог, когда видит сбои процесса.

Добавьте несколько журнальных сообщений в верхнюю часть вашего обработчика, чтобы узнать, попадает ли он туда. Распечатайте результат из getDefaultUncaughtExceptionHandler, а затем выбросьте неперехваченное исключение, чтобы вызвать сбой. Следите за выходом logcat, чтобы узнать, что происходит.

Я опубликовал простое решение для пользовательской обработки Android-сбоев давным-давно. Это немного взломанный, но он работает на всех версиях Android (включая Lollipop).

Сначала немного теории. Основные проблемы, связанные с использованием обработчика исключенных обработчиков на Android, включают исключения, которые были выбраны в основном (aka UI) потоке. И вот почему. Когда приложение запускает системные вызовы ActivityThread.main, который подготавливает и запускает главный петлитель вашего приложения:

 public static void main(String[] args) { … … Looper.prepareMainLooper(); … Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } 

Основной петлевой механизм отвечает за обработку сообщений, отправленных в потоке пользовательского интерфейса (включая все сообщения, связанные с отображением и взаимодействием интерфейса). Если исключение выбрано в потоке пользовательского интерфейса, оно будет улавливаться вашим обработчиком исключений, но поскольку вы не используете метод loop() вы не сможете показать какой-либо диалог или активность для пользователя, поскольку никто не может Обрабатывать сообщения пользовательского интерфейса для вас.

Предлагаемое решение довольно простое. Мы запускаем метод Looper.loop самостоятельно и окружаем его блоком try-catch. Когда исключение поймано, мы обрабатываем его, как мы хотим (например, запустите нашу пользовательскую активность отчета) и снова Looper.loop метод Looper.loop .

Следующий метод демонстрирует эту технику (ее следует вызывать из Application.onCreate ):

 private void startCatcher() { UncaughtExceptionHandler systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler(); // the following handler is used to catch exceptions thrown in background threads Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler(new Handler())); while (true) { try { Looper.loop(); Thread.setDefaultUncaughtExceptionHandler(systemUncaughtHandler); throw new RuntimeException("Main thread loop unexpectedly exited"); } catch (Throwable e) { showCrashDisplayActivity(e); } } } 

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

 static class UncaughtHandler implements UncaughtExceptionHandler { private final Handler mHandler; UncaughtHandler(Handler handler) { mHandler = handler; } public void uncaughtException(Thread thread, final Throwable e) { mHandler.post(new Runnable() { public void run() { throw new BackgroundException(e); } }); } } 

Пример проекта, который использует эту технику, доступен на моем репозитории GitHub: https://github.com/idolon-github/android-crash-catcher

FWIW Я знаю, что это немного не по теме, но мы с успехом используем свободный план Crittercism . Они также предлагают некоторые премиальные функции, такие как обработка исключения, поэтому приложение не разбивается.

В бесплатной версии пользователь все еще видит крах, но по крайней мере я получаю электронную почту и трассировку стека.

Мы также используем версию iOS (но я слышал от своих коллег, что это не так хорошо).


Вот похожие вопросы:

  • Глобальный неперехваченный обработчик исключений -> журнал электронной почты для меня?
  • Возможно ли создать какой-либо глобальный обработчик исключений в Android?

Я думаю, чтобы отключить это в вашем методе uncaughtException (), не вызывайте previousHandler.uncaughtException (), где previousHandler задается

 previousHandler = Thread.getDefaultUncaughtExceptionHandler(); 

Это не работает, пока вы не позвоните

 android.os.Process.killProcess(android.os.Process.myPid()); 

В самом конце вашего UncaughtExceptionHandler.