2013-07-07 2 views
7

Я занимаюсь разработкой приложения, и время от времени у одного из моих рабочих рабочих потоков есть неперехваченное исключение того или иного типа. Эти исключения разбивают этот поток, но поскольку он не работает в потоке пользовательского интерфейса, приложение продолжает работать. Как я могу заставить эти неперехваченные исключения в фоновом потоке разбивать все приложение? Было бы неплохо, если бы была доступна одна и та же контекстная информация о сбоях (например, трассировка стека).Android: Force Crash with Uncaught Exception in Thread

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

ответ

0

вы можете поймать свое неперехваченное исключение в классе, которое реализует java.lang.Thread.UncaughtExceptionHandler.

  • создать класс, который реализует UncaughtExceptionHandler и поставить поведение, которое вы хотите в uncaughtException overidden функции.
    вы можете сделать в этой функции любое поведение, которое вы хотите, например, отправить журналы на сервер, показать пользовательский диалог сбоев и т. Д.
  • в вашей деятельности/нитью добавить Thread.setDefaultUncaughtExceptionHandler(); и укажите экземпляр класса обработчика исключений.


+0

Это не работает для всех реализаций Исполнителя. Некоторые из них не называют обработчика. Вы должны переопределить 'afterExecute' и повторно удалить RuntimeException или Error, чтобы заставить его сбой. – Monstieur

2

поздний ответ, но я задавал себе тот же вопрос.

Мы используем Crashlytics в Production, но если приложение построено для разработки, некоторое утверждение разрешено, и на самом деле это приводит к регистрации ошибки, поэтому разработчик может обнаружить любое неправильное поведение.

Но, как вы заметили, выброс ошибки в фоновом потоке не приведет к сбою приложения.

Чтобы гарантировать, что приложение немедленно сработает при сборке для разработки, мы просто используем обработчик на основном петлере, чтобы исключить исключение из основного потока.

Это выглядит как это:


public static void assertTrue(boolean condition, String msg) { 
    if (condition) { 
     return; 
    } 

    final IllegalStateException e = new IllegalStateException(message); 
    if (BuildConfig.RELEASE) { 
     Crashlytics.logException(e); 
     return; 
    } 

    Log.e("ASSERT", message, e); 
    if (Looper.getMainLooper() != Looper.myLooper()) { 
     mMainThreadHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       throw e; 
      } 
     }); 
    } 

    throw e; 
} 
+0

Хотя это выглядит многообещающим решением, для меня несколько неясных: 1. Как вы избегаете ошибок Intellij для «неперехваченного исключения» в run() 2. Где вы получаете mainThreadHandler в этом статическом контексте? –

0

Оригинальная версия ниже

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

public static <T extends Exception> void throwOnMainThread(T exception) { 
    Thread mainThread = Looper.getMainLooper().getThread(); 
    mainThread.getUncaughtExceptionHandler().uncaughtException(mainThread, exception); 
} 

Это приведет к краху основного потока из любой точки мира и безопасно звонить даже без установки пользовательских UncaughtExceptionHandler.

Оригинальный ответ:

Рассмотрим следующий статический метод сбой основной поток от фонового потока:

public static <T extends Exception> void throwOnMainThread(final T exception) { 
    Handler mainThreadHandler = new Handler(Looper.getMainLooper()); 
    mainThreadHandler.post(new Runnable() { 
     @Override 
     public void run() { 
      Thread currentThread = Thread.currentThread(); 
      currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, exception); 
     } 
    }); 
} 

Во-первых, мы получаем Handler для главного потока через основной петлителя.Затем мы отправляем Runnable, который будет вызывать UncaughtExceptionHandler этого потока и передать его нашему исключению.

Поместите это в класс utils, и вы сможете исключать исключения из основного потока из любого места.

Сбоев основного потока затем может быть достигнут при использовании

ThreadUtils.throwOnMainThread(new RuntimeException()); 

, например.