Использование глобальной обработки исключений на Android - PullRequest
54 голосов
/ 13 декабря 2010

Есть ли пример кода или учебное пособие по использованию метода Thread.setDefaultUncaughtExceptionHandler?По сути, я пытаюсь отобразить в моем приложении настраиваемое диалоговое окно с предупреждением, когда возникает исключение.Можно ли сделать это?Я знаю, что немного сложно отобразить что-то на экране, если исключение выдается в потоке пользовательского интерфейса, но я не знаю обходного пути для этого.

Ответы [ 5 ]

72 голосов
/ 16 января 2012

Базовый пример для того, кто заходит на эту страницу с решением :)

public class ChildActivity extends BaseActivity {
    @SuppressWarnings("unused")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int a=1/0;
    }
}

Класс для обработки ошибки:

public class BaseActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
                Log.e("Alert","Lets See if it Works !!!");
            }
        });
    }
}
33 голосов
/ 25 октября 2014

Вот вариант ответа от Мохит Шарма со следующими улучшениями:

  • Не вызывает зависания приложения / службы после обработки ошибки
  • Позволяет Android нормально обрабатывать ошибки после вашего

Код:

public class BaseActivity extends Activity {
    @Override
    public void onCreate() {
        super.onCreate();

        final Thread.UncaughtExceptionHandler oldHandler =
            Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler(
            new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(
                    Thread paramThread,
                    Throwable paramThrowable
                ) {
                    //Do your own error handling here

                    if (oldHandler != null)
                        oldHandler.uncaughtException(
                            paramThread,
                            paramThrowable
                        ); //Delegates to Android's error handling
                    else
                        System.exit(2); //Prevents the service/app from freezing
                }
            });
    }
}
4 голосов
/ 06 июля 2011

Имейте в виду, что The RuntimePermission("setDefaultUncaughtExceptionHandler") проверяется перед установкой обработчика, и убедитесь, что впоследствии вы вызвали остановку процесса, выдав необработанное исключение, поскольку все может быть в неопределенном состоянии.

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

2 голосов
/ 11 января 2019

Я просто хотел рассказать о своем опыте.Я использую решение, предложенное https://stackoverflow.com/a/26560727/2737240, чтобы сбросить исключение в файл журнала перед передачей управления обработчику исключений по умолчанию.

Однако моя структура выглядит следующим образом:

          BaseActivity
               |
    _______________________
    |          |          |
Activity A Activity B Activity C
final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();                                                                                                                                                                                                                                                                                                                              
    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {                                                                                                                                                                                                                                                                                                                                           
        @Override                                                                                                                                                                                                                                                                                                                                                                                                               
        public void uncaughtException(Thread thread, Throwable e) {                                                                                                                                                                                                                                                                                                                                                             
            handleUncaughtException(thread, e, defaultEH);                                                                                                                                                                                                                                                                                                                                                                      
        }                                                                                                                                                                                                                                                                                                                                                                                                                       
 });

, где handleUncaughtException(thread, e, defaultEH); записывает в журнал и передает вызов исходному UncaughtExceptionHandler.

Итак, с помощью этого кода произошло следующее:

  • Создано действие A
  • Новый обработчик исключений по умолчанию (DEH) теперь мой обработчик журнала +старый DEH
  • Создается экземпляр действия B
  • Новый DEH теперь является моим обработчиком журнала + старый DEH (обработчик журнала + исходный DEH)
  • Создается действие C
  • Новый DEH теперь является моим обработчиком журналов + старый DEH (обработчик журналов + обработчик журналов + оригинальный DEH)

Таким образом, эта цепочка бесконечно растет, вызывая две проблемы:

  1. Указанный пользовательский код (в моем случае запись в файл журнала) будет вызываться несколько раз, что не является желаемым действием.
  2. Ссылка на defaultEh сохраняется в куче даже после завершения действияпотому что он используется цепочкой ссылок, поэтому самое худшее, что может произойти, это исключение нехватки памяти.

Поэтому я добавил еще одну вещь, чтобы наконец-то сделать эту работу без проблем:

private static boolean customExceptionHandlerAttached = false;                                                                                                                                                                                                                                                                                                                                                                      

@Override                                                                                                                                                                                                                                                                                                                                                                                                                           
protected void onCreate(@Nullable Bundle savedInstanceState) {                                                                                                                                                                                                                                                                                                                                                                      
    super.onCreate(savedInstanceState);                                                                                                                                                                                                                                                                                                                                                                                             

    if(!customExceptionHandlerAttached) {                                                                                                                                                                                                                                                                                                                                                                                            
        final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();                                                                                                                                                                                                                                                                                                                              
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {                                                                                                                                                                                                                                                                                                                                           
            @Override                                                                                                                                                                                                                                                                                                                                                                                                               
            public void uncaughtException(Thread thread, Throwable e) {                                                                                                                                                                                                                                                                                                                                                             
                 handleUncaughtException(thread, e, defaultEH);                                                                                                                                                                                                                                                                                                                                                                      
            }                                                                                                                                                                                                                                                                                                                                                                                                                       
        });                                                                                                                                                                                                                                                                                                                                                                                                                         
        customExceptionHandlerAttached = true;                                                                                                                                                                                                                                                                                                                                                                                      
    }                                                                                                                                                                                                                                                                                                                                                                                                                               
}

С помощью этого решения мы можем убедиться, что:

  • добавим пользовательский обработчик исключений для нашего желаемого действия
  • , чтобы убедиться, что это действие запускается только один раз
  • позволяя сборщику мусора полностью избавиться от нашей деятельности, вызывая finish ()
2 голосов
/ 31 июля 2018

, если вы хотите использовать эту библиотеку

https://github.com/selimtoksal/Android-Caught-Global-Exception-Library

создать свой TransferObject не все в ваших действиях, просто используйте в Базовое действие

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...