2013-07-07 4 views
7

Ich entwickle eine App, und ab und zu einer meiner Hintergrund-Worker-Threads wird eine nicht abgefangene Ausnahme der einen oder anderen Art haben. Diese Ausnahmen führen zum Absturz des Threads. Da er jedoch nicht im UI-Thread enthalten ist, wird die App weiterhin ausgeführt. Wie kann ich diese nicht abgefangenen Ausnahmen in den Hintergrundthreads erzwingen, um die gesamte App zum Absturz zu bringen? Es wäre schön, wenn die gleichen kontextabhängigen Informationen zum Absturz (wie der Stack-Trace) verfügbar wären.Android: Force Crash mit Uncaught Ausnahme in Thread

Ich möchte dies tun, damit, wenn ich die App zu meinen Testern freigeben nicht reagiert. Wenn der Hintergrund-Thread eine nicht abgefangene Ausnahme hat, geht die App stattdessen zum Crash-Handler und sendet mir einen Bericht (ich benutze ACRA, aber das sollte nichts ausmachen). Das ist besser als eine App, die im Stillen fehlschlägt.

Antwort

0

Sie können Ihre nicht abgefangene Ausnahme in der Klasse abfangen, die java.lang.Thread.UncaughtExceptionHandler implementieren.

  • eine Klasse erstellen, die UncaughtExceptionHandler implementiert und das Verhalten, das Sie in uncaughtException außer Kraft gesetzt Funktion möchten setzen.
    Sie können in dieser Funktion jedes Verhalten tun, wie Protokolle an den Server senden, benutzerdefinierten Crash-Dialog für Benutzer etc.
  • in Ihrer Aktivität/Thread hinzufügen Thread.setDefaultUncaughtExceptionHandler(); und geben Sie eine Instanz Ihrer Exception-Handler-Klasse an.


+0

Dies funktioniert nicht bei allen Executor-Implementierungen. Einige von ihnen rufen den Handler nicht an. Sie müssen 'afterExecute' überschreiben und die RuntimeException oder Error von dort erneut auslösen, um es zum Absturz zu zwingen. – Monstieur

2

Späte Antwort, aber ich mir die gleiche Frage stellte. Wir verwenden Crashlytics in der Produktion, aber wenn die App für die Entwicklung erstellt wird, sind einige Assertion aktiviert, und die Protokollierung eines Fehlers löst sie tatsächlich aus, so dass wir Entwickler jedes falsche Verhalten erkennen können.

Aber wie Sie bemerkt haben, stürzt ein Fehler in einem Hintergrund-Thread die App nicht ab.

Um sicherzustellen, dass die App sofort abstürzt, wenn sie für die Entwicklung erstellt wird, verwenden wir einfach einen Handler auf dem Hauptlooper, um die Ausnahme auf den Hauptthread zu werfen.

Es sieht ein bisschen wie folgt:


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

Während dies wie eine vielversprechende Lösung aussieht, sind mir einige Dinge unklar: 1. Wie vermeiden Sie Intellij Fehler für "Uncaught Exception" in run() 2. Wo erhalten Sie den MainThreadHandler in diesem statischen Kontext? –

0

Originalversion unter

Eigentlich nach weiteren Tests habe ich gefunden, dass Sie Ihren Code nur durch Übergabe der Ausnahme zu Ihrem Haupt-Thread vereinfachen direkt.

Dies wird den Haupt-Thread von überall abstürzen und ist sicher zu rufen, auch ohne einen benutzerdefinierten UncaughtExceptionHandler zu setzen.

Ursprüngliche Antwort:

Betrachten Sie die folgende statische Methode für den Haupt-Thread von einem Hintergrund-Thread Absturz:

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

Zuerst haben wir einen Handler für das Hauptthread über die Haupt Looper bekommen.Dann veröffentlichen wir eine Runnable, die den UncaughtExceptionHandler dieses Threads aufruft und uns unsere Exception gibt.

Setzen Sie dies in eine utils-Klasse und Sie können Ausnahmen auf dem Hauptthread grundsätzlich von überall abwerfen.

den Haupt-Thread Abstürzt dann unter Verwendung

ThreadUtils.throwOnMainThread(new RuntimeException()); 

beispielsweise dadurch erreicht werden könnte.