Есть ли пример кода или учебное пособие о том, как использовать метод Thread.setDefaultUncaughtExceptionHandler
? По сути, я пытаюсь отобразить в моем приложении настраиваемое диалоговое окно с предупреждением, когда возникает исключение. Можно ли сделать это? Я знаю, что немного сложно отобразить что-то на экране, если исключение выдается в потоке пользовательского интерфейса, но я не знаю, как это обойти.
Использование глобальной обработки исключений на Android
Ответ 1
Основной пример для тех, кто приходит на эту страницу с решением :)
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 !!!");
}
});
}
}
Ответ 2
Здесь вариант от Mohit Sharma со следующими улучшениями:
- Не вызывает зависание приложения/службы после обработки ошибок.
- Позволяет 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 error handling
else
System.exit(2); //Prevents the service/app from freezing
}
});
}
}
Ответ 3
Имейте в виду, что параметр The RuntimePermission("setDefaultUncaughtExceptionHandler")
проверяется перед установкой обработчика и убедитесь, что вы заставляете процесс останавливаться после этого, бросая неперехваченное исключение, поскольку все может быть в неопределенном состоянии.
Не отображать ничего, действительно, поток пользовательского интерфейса, возможно, был разбит, записывать журнал и/или отправлять данные на сервер. Возможно, вы захотите проверить этот вопрос и его ответы.
Ответ 4
если вы хотите использовать эту библиотеку
https://github.com/selimtoksal/Android-Caught-Global-Exception-Library
создать свой TransferObject не все в вашей деятельности, просто использовать в базовой деятельности
Ответ 5
Я просто хотел показать свой опыт до сих пор. Я использую решение, предложенное fooobar.com/questions/129142/... чтобы сбросить исключение в мой файл журнала, прежде чем передать управление обработчику исключений по умолчанию.
Тем не менее, моя структура выглядит так:
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.
Итак, что случилось с использованием этого кода было следующее:
- Деятельность А создается
- Новый обработчик исключений по умолчанию (DEH) теперь мой обработчик журнала + старый DEH
- Деятельность B создается
- Новый DEH теперь мой обработчик журнала + старый DEH (обработчик журнала + оригинальный DEH)
- Деятельность C создается
- Новый DEH теперь мой обработчик журнала + старый DEH (обработчик журнала + обработчик журнала + оригинальный DEH)
Таким образом, это бесконечно растущая цепь, вызывающая две проблемы:
- Указанный пользовательский код (в моем случае запись в файл журнала) будет вызываться несколько раз, что не является желаемым действием.
- Ссылка на 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()
Ответ 6
Вы можете обработать необработанные исключения с помощью библиотеки FireCrasher и выполнить восстановление из нее.
Вы можете узнать больше о библиотеке в этой средней статье