Basit çözümü gönderdimUzun zaman önce Android çökmelerinin özel olarak işlenmesi için . Biraz karmaşık ancak tüm Android sürümlerinde (Lollipop dahil) çalışıyor.
İlk önce biraz teori. Android'de yakalanmamış istisna işleyiciyi kullandığınızda ana sorunlar, ana (UI) iş parçacığında atılan istisnalarla birlikte gelir. Ve işte nedeni. Uygulama başladığında, uygulamanızın Ana döngüleyicisini hazırlayan ve başlatan ActivityThread.main yöntemini çağırır :
public static void main(String[] args) {
…
…
Looper.prepareMainLooper();
…
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
Ana döngüleyici, UI iş parçacığına gönderilen mesajların işlenmesinden sorumludur (UI oluşturma ve etkileşimle ilgili tüm mesajlar dahil). UI iş parçacığına bir istisna atılırsa, istisna işleyiciniz tarafından yakalanır, ancakloop()
yöntemin için, UI mesajlarını işleyecek kimse kalmadığı için kullanıcıya herhangi bir iletişim kutusu veya etkinlik gösteremezsiniz. senin için.
Önerilen çözüm oldukça basit. Looper.loop
Yöntemi kendi başımıza çalıştırıyoruz ve onu try-catch bloğu ile çevreliyoruz. Bir istisna yakalandığında, onu istediğimiz gibi işleriz (örneğin, özel rapor etkinliğimizi başlatırız) ve Looper.loop
yöntemi tekrar çağırırız .
Aşağıdaki yöntem bu tekniği göstermektedir ( Application.onCreate
dinleyiciden çağrılmalıdır ):
private void startCatcher() {
UncaughtExceptionHandler systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler(new Handler()));
while (true) {
try {
Looper.loop();
Thread.setDefaultUncaughtExceptionHandler(systemUncaughtHandler);
throw new RuntimeException("Main thread loop unexpectedly exited");
} catch (Throwable e) {
showCrashDisplayActivity(e);
}
}
}
Gördüğünüz gibi yakalanmamış istisna işleyicisi yalnızca arka plan iş parçacıklarında atılan istisnalar için kullanılır. Aşağıdaki işleyici, bu istisnaları yakalar ve bunları UI iş parçacığına yayar:
static class UncaughtHandler implements UncaughtExceptionHandler {
private final Handler mHandler;
UncaughtHandler(Handler handler) {
mHandler = handler;
}
public void uncaughtException(Thread thread, final Throwable e) {
mHandler.post(new Runnable() {
public void run() {
throw new BackgroundException(e);
}
});
}
}
Bu tekniği kullanan örnek bir proje GitHub depomda mevcuttur: https://github.com/idolon-github/android-crash-catcher