Я хочу установить глобальный обработчик исключенных исключений для всех потоков в приложении для Android. Итак, в моем подклассе Application
я установил реализацию Thread.UncaughtExceptionHandler
как обработчик по умолчанию для неперехваченных исключений.
Thread.setDefaultUncaughtExceptionHandler(
new DefaultExceptionHandler(this));
В моей реализации я пытаюсь показать AlertDialog
отображение соответствующего сообщения об исключении.
Однако это не работает. Всякий раз, когда вызывается исключение для любого потока, который не обрабатывается, я получаю запас, диалог по умолчанию ОС ( "Извините! -Application-has-stop-неожиданный диалог" ).
Каков правильный и идеальный способ установки обработчика по умолчанию для неперехваченных исключений?
Ответ 1
Это должно быть все, что вам нужно. (Убедитесь, что вы заставляете процесс останавливаться после этого - все может быть в неопределенном состоянии.)
Первое, что нужно проверить, - это вызов обработчика Android. Возможно, что ваша версия вызывается, но неудачно, и системный_сервер показывает общий диалог, когда видит сбои процесса.
Добавьте несколько сообщений журнала вверху вашего обработчика, чтобы узнать, попадает ли он туда. Распечатайте результат из getDefaultUncaughtExceptionHandler, а затем отбросьте неперехваченное исключение, чтобы вызвать сбой. Следите за выходом logcat, чтобы узнать, что происходит.
Ответ 2
Я опубликовал простое решение для пользовательской обработки 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
еще раз.
Следующий метод демонстрирует этот метод (его следует вызывать из прослушивателя 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
Ответ 3
Я думаю, что отключить это в вашем методе uncaughtException() не вызывать previousHandler.uncaughtException(), где previousHandler задается
previousHandler = Thread.getDefaultUncaughtExceptionHandler();
Ответ 4
FWIW Я знаю, что это немного не по теме, но мы с успехом использовали "Бесплатный критерий" . Они также предлагают некоторые премиальные функции, такие как обработка исключения, поэтому приложение не сбой.
В бесплатной версии пользователь по-прежнему видит сбой, но по крайней мере я получаю электронную почту и трассировку стека.
Мы также используем версию iOS (но я слышал от своих коллег, что это не совсем так).
Вот похожие вопросы:
Ответ 5
Это не работает, пока вы не вызовете
android.os.Process.killProcess(android.os.Process.myPid());
в самом конце вашего UncaughtExceptionHandler.
Ответ 6
Вы можете обработать необработанные исключения с помощью библиотеки FireCrasher и выполнить восстановление из нее.
Вы можете узнать больше о библиотеке в этой средней статье