8

Ich verwende diesen Code, um alle nicht abgefangenen Ausnahmen zu behandeln, die zum Absturz meiner Anwendung führen können.Toast wird nicht in UnCaughtExceptionHandler angezeigt

public class ExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler { 
    private final Context myContext; 

    public ExceptionHandler(Context context) { 

     myContext = context; 
    } 

    public void uncaughtException(Thread thread, Throwable exception) { 

     Toast.makeText(myContext, 
       "The application has crashed, and a report is sent to the admin", 
       Toast.LENGTH_SHORT).show(); 
     StringWriter stackTrace = new StringWriter(); 
     exception.printStackTrace(new PrintWriter(stackTrace)); 
     System.err.println(stackTrace);// You can use LogCat too 
     Intent intent = new Intent(myContext, CrashActivity.class); 
     myContext.startActivity(intent); 
     Process.killProcess(Process.myPid()); 
     System.exit(10); 
    } 
} 

Wenn ich es mit einem bekannten aber nicht abgefangene Ausnahme laufen (nur zum Testen), Aktivität „CrashActivity“ genannt wird, aber der Toast, die, bevor es kommen muss, zeigt sich nicht.

Eigentlich wollte ich nur Toast zeigen und dann myContext.finish() aufrufen; anstatt zur CrashActivity zu gehen. Aber dieser Toast ist nicht sichtbar.

Wo liege ich falsch?

+2

Ich bin kein Android-Programmierer, aber aus der Lesung, die ich getan habe, muss nicht auf dem UI-Thread Toast aufgerufen werden? In diesem Fall rufen Sie es im UI-Thread auf? Ich vermute, dass du wahrscheinlich schon daran gedacht hast. –

+0

yeah du hast Recht .. ich rufe nicht den Toast auf ui Faden an :( –

Antwort

3

Sie sind wahrscheinlich der Toast aus einem Thread aufrufen, während ein Toast sollte ... aus dem UI-Thread aufgerufen werden

Wenn dies nicht hilft, bitte geben Sie uns die logcat Ausgang so können wir sehen, welche Art von Fehler, den Sie bekommen.

+0

Yeah ich bin falsch in der Verwendung der Toast in einem anderen Thread. Wirklich sah ich dies in einer Anwendung, wo, wenn die App abstürzt zeigt es einen Toast auf der gleiche Aktivität.Es ist, dass es tatsächlich erinnert die gleiche Aktivität und zeigt dann den Toast ?? –

7

Diese Frage beim googeln für genau das gleiche Problem gefunden. Soweit ich feststellen kann, ist es nicht notwendig, dass der Toast.show() aus dem UI-Thread aufgerufen wird, solange es einen Anwendungskontext gibt.

AFAIK: Das Problem, das hier auftritt, ist das Folgende: Sie versuchen, einen Toast zu zeigen und sofort danach wird Ihre Anwendung von der VM heruntergefahren, was bedeutet, dass Ihr Toast ebenfalls heruntergefahren wird.

Eine Lösung für das Problem ist folgendes:

  • Führen Sie den Toast aus einem sepearate Thema
  • Verzögerung Abschaltung Ihrer Anwendung in der nicht erfassten Ausnahme Handler.

Was ich tue, ist die folgende:

In Application::onCreate():

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { 
    @Override 
    public void uncaughtException(Thread thread, Throwable ex) 
    { 
     new Thread() { 
      @Override 
      public void run() { 
       Looper.prepare(); 
       Toast.makeText(getApplicationContext(), "Application crashed", Toast.LENGTH_LONG).show(); 
       Looper.loop(); 
      } 
     }.start(); 

     try 
     { 
      Thread.sleep(4000); // Let the Toast display before app will get shutdown 
     } 
     catch (InterruptedException e) 
     { 
      // Ignored. 
     } 
    } 
}); 

Es ist ähnlich, wie der Toast Benachrichtigung in ACRA arbeitet (in der Tat das ist, wo ich den Hinweis bekam von) .

+0

Dies war genau das, was ich brauchte, da ich wollte eine schnelle (vorläufige) Weg, um einige Details der Ausnahme zu sehen.Ich fand ich musste auch setzen in einem 'System.exit()' Aufruf nach dem 'catch' Block.Fehlt das oben? – darrenp

+0

Pjuh. Gute Frage. Ich schließe nicht mit 'System.exit()' ab, sondern benutze den Standard-Exception-Handler mit '_androidDefaultUncaughtExHandler.uncaughtException (thread, ex);' und setze ihn mit '_androidDefaultUncaughtExHandler = Thread.getDefaultUncaughtExceptionHandler();' – GeneSys

+1

Macht Sinn. Der standardmäßige Ausnahmebehandler muss aufräumen und 'System.exit()' aufrufen. – darrenp

3

Aufruf von System.exit(0) aus Android UncaughtExceptionHandler hilft Anwendung wiederherstellen von Fehler und Neustart letzte Aktivität. IMHO, Benutzererfahrung wird deutlich verbessert. Dieser Ansatz muss jedoch auf mehreren Android-Plattformen erprobt und getestet werden. Habe das bei GB und JB probiert. Es hat gut funktioniert. Außerdem habe ich von anderen gehört (ich bin neu in Android), dass das Aufrufen von System.exit() nicht in Android empfohlen wird, aber ... könnte dies als eine schöne Wiederherstellungsoption für Android-Anwendungen verwendet werden.

public void uncaughtException(Thread thread, Throwable ex) { 
     new Thread() { 
      @Override 
      public void run() { 
       Looper.prepare(); 
       Toast.makeText(YourActivity.this, "Application has Crashed. Recovering now.", Toast.LENGTH_LONG).show(); 
       /* Log relevant message/analytics from here. */ 
       System.exit(1); 
       Looper.loop(); 
      } 
     }.start(); 
    } 
+0

Wie kann ich? Vermeiden Sie den Neustart der App, wenn ich System.exit() aufrufen? Ich möchte, dass die App sich selbst schließt, wenn es einen Absturz gibt, aber ich möchte das Ereignis erfassen und die Daten per E-Mail senden ... –

+0

'System.exit()' wird in den meisten Fällen die App abrupt schließen, was in der Regel ist nicht was du willst. Die App wird abstürzen, wenn Sie 'exit()' aufrufen oder nicht, so dass es nicht nötig ist, sie explizit aufzurufen. – milosmns