2013-07-07 16 views
7

Sto sviluppando un'applicazione, e di tanto in tanto uno dei miei thread di lavoro in background avrà un'eccezione non rilevata di un tipo o dell'altro. Queste eccezioni bloccano quel thread, ma poiché non è sul thread dell'interfaccia utente, l'app continua a funzionare. Come posso forzare queste eccezioni non catturate nei thread in background per bloccare l'intera app? Sarebbe bello se fossero disponibili le stesse informazioni di crash contestuali (come la traccia dello stack).Android: Blocco forzato con eccezione non rilevata nella discussione

Voglio fare questo in modo che quando rilascio l'app ai miei tester non diventi insensibile. Invece, quando il thread in background ha un'eccezione non rilevata, l'App andrà al suo gestore di crash e mi invierà un report (sto usando ACRA, ma non dovrebbe importare). È meglio di un'app che fallisce silenziosamente.

risposta

0

è possibile catturare l'eccezione non catturata in classe che implementa java.lang.Thread.UncaughtExceptionHandler.

  • creare una classe che implementa l'UncaughtExceptionHandler e mettere il comportamento che si desidera in uncaughtException funzione overidden.
    si può fare in questa funzione qualsiasi comportamento si desideri inviare registri al server, mostrare la finestra di dialogo di arresto anomalo personalizzata all'utente ecc.
  • nella propria attività/thread aggiungere Thread.setDefaultUncaughtExceptionHandler(); e fornire un'istanza della classe del gestore di eccezioni.


+0

Questo non funziona per tutte le implementazioni di Executor. Alcuni di loro non chiamano il conduttore. Devi eseguire l'override di "afterExecute" e ribaltare RuntimeException o Error da lì per forzare l'arresto anomalo. – Monstieur

2

risposta tardi, ma mi chiedevo la stessa domanda.

Utilizziamo i Crashlytics in produzione, ma se l'app è stata sviluppata per lo sviluppo, alcune asserzioni sono abilitate e la registrazione di un errore lo lancia in realtà, in modo che lo sviluppatore possa rilevare qualsiasi comportamento errato.

Ma come hai notato, lanciare un errore in un thread in background non causa il crash dell'applicazione.

Per garantire che l'app si blocchi immediatamente durante la compilazione per lo sviluppo, è sufficiente utilizzare un gestore sul looper principale per generare l'eccezione sul thread principale.

sembra un po 'come questo:


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

Mentre questa sembra una soluzione promettente, alcune cose non sono chiare: 1. Come si evitano gli errori Intellij per "eccezione non rilevata" in run() 2. Dove si ottiene mainThreadHandler in questo contesto statico? –

0

versione originale sotto

In realtà, dopo ulteriori test ho trovato che è possibile semplificare il codice, semplicemente consegnando l'eccezione al thread principale direttamente.

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

Questa andrà in crash il thread principale da qualsiasi luogo ed è sicuro da chiamare anche senza impostare una consuetudine UncaughtExceptionHandler.

risposta originale:

Si consideri il seguente metodo statico per schiantarsi il thread principale da un thread in background:

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); 
     } 
    }); 
} 

In primo luogo si ottiene un gestore per il thread principale attraverso il principale Looper.Quindi pubblichiamo un Runnable che invocherà l'UncaughtExceptionHandler di quel thread e lo consegnerà alla nostra eccezione.

Inseritelo in una classe di utilità e sarete in grado di generare eccezioni sul thread principale praticamente da qualsiasi posizione.

Danneggiamento il filo principale potrebbe allora essere realizzato utilizzando

ThreadUtils.throwOnMainThread(new RuntimeException()); 

per esempio.

Problemi correlati