6

Poprosiłem this pytanie jakiś czas temu na Stackoverflow odpowiedź pracował dla mnie, to nadpisuje handleUncaughtException, zapisać wyjątek i rzuca domyślnego Unfortunately app has stopped working, ale kiedy włączone to w moim app , Mam do czynienia z problemem.Jak zastąpić handleUncaughtException bez zmiany jego funkcjonalność

Oto odpowiedź, którą otrzymałem.

private Thread.UncaughtExceptionHandler defaultExceptionHandler; 

    public void registerCrash(){ 
     defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); 

     Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){ 
      @Override 
      public void uncaughtException (Thread thread, Throwable e){ 
       handleUncaughtException (thread, e); 
       if(defaultExceptionHandler != null){ 
        defaultExceptionHandler.uncaughtException(thread, e); 
       } 
      } 
     }); 
    } 

Co robi, najpierw idzie do handleUncaughtException (thread, e); zapisać dziennik awarii w tej metodzie, to czyta ten wiersz

if(defaultExceptionHandler != null){ 
    defaultExceptionHandler.uncaughtException(thread, e); 
} 

tutaj rzucamy przechwycony wyjątek ponownie, więc idzie do pierwszej linii ponownie, i ponownie zapisuje wyjątek, i to idzie w pętli, a aplikacja nie odpowiada.

Co chcę, to zapisać dziennik awarii, a następnie wyświetlić domyślną wiadomość Unfortunate użytkownikowi.

EDIT

dniu uruchomienia aplikacji to czyta to;

defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); 

przypadku awarii aplikacji, odczytuje te linie

Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){ 
    @Override 
    public void uncaughtException (Thread thread, Throwable e){ 

     handleUncaughtException (thread, e); //Custom Method 

     if(defaultExceptionHandler != null){ 
      defaultExceptionHandler.uncaughtException(thread, e); 
     } 
    } 

Więc najpierw idzie do handleUncaughtException() tam mam pod warunkiem zwyczaj wdrożenie, a potem idzie na ten cel;

if(defaultExceptionHandler != null){ 
    defaultExceptionHandler.uncaughtException(thread, e); 
} 

The defaultExceptionHandler nigdy nie jest pusta; W przypadku wielokrotnych awarii uruchamia się w pętli.

Próbowałem dodać tam count, ale za każdym razem było 0.

+0

'Więc to idzie w pętli w przypadku wielokrotności crashes "czy możesz wskazać na taki scenariusz? Co powoduje inny wyjątek? – azizbekian

+0

@azizbekian: Nie mogłem znaleźć kroków, aby go zmienić. To nie zdarza się za każdym razem, ale czasami – Kirmani88

+0

czym jest metoda defaultExceptionHandler. Czy to twoja własna metoda? jeśli tak, opublikuj ten kod metody. I post kodu handleUncaughtException (thread, e) też –

Odpowiedz

1

Najbardziej prawdopodobnym wyjaśnieniem jest to, że twoja metoda registerCrash() jest wywoływana dwukrotnie.

Po raz pierwszy rejestrujesz się Handler 1; w tym momencie nie ma domyślnego programu obsługi, więc ustawia on defaultExceptionHandler na . Po raz drugi rejestrujesz Handler 2, a następnie aktualizujesz defaultExceptionHandler, aby wskazać Handler 1.

W przypadku nieprzechwyconego wyjątku najpierw zostaje wywołany Handler 2. Wywołuje niestandardową metodę obsługi, a następnie wywołuje defaultExceptionHandler, która teraz wskazuje na Handler 1.

Handler 1 zostaje wywołana. Wywołuje niestandardową procedurę obsługi po raz drugi, a następnie wywołuje defaultExceptionHandler, , która teraz wskazuje na siebie. Ten krok powtarza się, aż do przepełnienia stosu.

Proponuję dwie zmiany. Najpierw dodaj strażnika, aby mieć pewność, że zarejestrujesz tylko jeden moduł obsługi wypadków. Po drugie, nie przechowuj procedury zastępczej w polu; przechwyć go w zamknięciu, aby wartość widoczna w twoim programie obsługi nigdy się nie zmieniła.

private static final AtomicBoolean CRASH_HANDLER_REGISTERED = new AtomicBoolean(); 

public void registerCrash() { 
    if (CRASH_HANDLER_REGISTERED.compareAndSet(false, true)) { 
     final Thread.UncaughtExceptionHandler defaultHandler = 
      Thread.getDefaultUncaughtExceptionHandler(); 

     Thread.setDefaultUncaughtExceptionHandler(
      new Thread.UncaughtExceptionHandler() { 
       @Override 
       public void uncaughtException(Thread thread, Throwable e) { 
        handleUncaughtException(thread, e); // Custom Method 

        if (defaultHandler != null) { 
         defaultHandler.uncaughtException(thread, e); 
        } 
       } 
      } 
     ); 
    } 
} 
0

Proponuję spróbować innego podejścia, unikać przesłanianie wyjątki, złapać ją i sprowadzaniu kod błędu, a to zrobić:

when x code with x conditions verify, do that

Powiązane problemy