AKTUALIZACJA: zobacz „zaakceptowane” rozwiązanie poniżej
Gdy moja aplikacja tworzy nieobsługiwany wyjątek, zamiast po prostu zakończyć działanie, chciałbym najpierw dać użytkownikowi możliwość wysłania pliku dziennika. Zdaję sobie sprawę, że robienie więcej pracy po uzyskaniu losowego wyjątku jest ryzykowne, ale hej, najgorsze jest to, że aplikacja kończy się zawieszać, a plik dziennika nie jest wysyłany. Okazuje się, że jest to trudniejsze niż się spodziewałem :)
Co działa: (1) przechwytywanie nieprzechwyconego wyjątku, (2) wyodrębnianie informacji dziennika i zapisywanie do pliku.
Co jeszcze nie działa: (3) rozpoczęcie działania polegającego na wysyłaniu wiadomości e-mail. Ostatecznie będę miał jeszcze jedną czynność, aby poprosić użytkownika o pozwolenie. Jeśli aktywność poczty e-mail działa, nie spodziewam się większych problemów dla drugiej osoby.
Sednem problemu jest to, że nieobsługiwany wyjątek jest przechwytywany w mojej klasie Application. Ponieważ to nie jest działanie, nie jest oczywiste, jak rozpocząć działanie z intencją.ACTION_SEND. Oznacza to, że zwykle w celu rozpoczęcia działania wywołuje się startActivity i wznawia za pomocą onActivityResult. Te metody są obsługiwane przez działanie, ale nie przez aplikację.
Jakieś sugestie, jak to zrobić?
Oto kilka wycinków kodu jako przewodnik początkowy:
public class MyApplication extends Application
{
defaultUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler();
public void onCreate ()
{
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler()
{
@Override
public void uncaughtException (Thread thread, Throwable e)
{
handleUncaughtException (thread, e);
}
});
}
private void handleUncaughtException (Thread thread, Throwable e)
{
String fullFileName = extractLogToFile(); // code not shown
// The following shows what I'd like, though it won't work like this.
Intent intent = new Intent (Intent.ACTION_SEND);
intent.setType ("plain/text");
intent.putExtra (Intent.EXTRA_EMAIL, new String[] {"[email protected]"});
intent.putExtra (Intent.EXTRA_SUBJECT, "log file");
intent.putExtra (Intent.EXTRA_STREAM, Uri.parse ("file://" + fullFileName));
startActivityForResult (intent, ACTIVITY_REQUEST_SEND_LOG);
}
public void onActivityResult (int requestCode, int resultCode, Intent data)
{
if (requestCode == ACTIVITY_REQUEST_SEND_LOG)
System.exit(1);
}
}
źródło
Odpowiedzi:
Oto kompletne rozwiązanie (prawie: pominąłem układ interfejsu użytkownika i obsługę przycisków) - pochodzące z wielu eksperymentów i różnych postów od innych osób związanych z problemami, które pojawiły się po drodze.
Jest kilka rzeczy, które musisz zrobić:
A teraz szczegóły:
(1 i 2) Obsłuż wyjątek uncaughtException, rozpocznij działanie dziennika wysyłania:
(3) Wyodrębnij dziennik (umieściłem to jako moje działanie SendLog):
(4) Uruchom aplikację e-mail (również w moim działaniu SendLog):
(3 i 4) Oto jak wygląda SendLog (musisz jednak dodać interfejs użytkownika):
(5) Manifest:
(6) Proguard konfiguracji:
W project.properties zmień wiersz konfiguracji. Musisz określić „optimize”, inaczej Proguard nie usunie wywołań Log.v () i Log.d ().
W proguard-project.txt dodaj następujący plik. To mówi Proguardowi, aby założył, że Log.v i Log.d nie mają żadnych skutków ubocznych (nawet jeśli robią to, ponieważ zapisują w dziennikach) i dlatego można je usunąć podczas optymalizacji:
Otóż to! Jeśli masz jakieś sugestie dotyczące ulepszeń, daj mi znać, a mogę to zaktualizować.
źródło
Obecnie istnieje wiele narzędzi do odtwarzania awaryjnego, które robią to łatwo.
crashlytics - narzędzie do zgłaszania awarii, bezpłatne, ale zapewnia podstawowe raporty. Zalety: Bezpłatne
Gryphonet - bardziej zaawansowane narzędzie do raportowania, wymaga pewnej opłaty. Zalety: łatwe odtwarzanie awarii, błędów ANR, spowolnienia ...
Jeśli jesteś prywatnym programistą, zasugerowałbym Crashlytics, ale jeśli jest to duża organizacja, wybrałbym Gryphonet.
Powodzenia!
źródło
Spróbuj zamiast tego użyć ACRA - obsługuje ona wysyłanie śladu stosu, a także wielu innych przydatnych informacji debugowania do zaplecza lub do skonfigurowanego dokumentu Dokumentów Google.
https://github.com/ACRA/acra
źródło
Odpowiedź @ PeriHartman działa dobrze, gdy wątek interfejsu użytkownika zgłasza nieprzechwycony wyjątek. Wprowadziłem pewne ulepszenia, gdy nieprzechwycony wyjątek jest generowany przez wątek spoza interfejsu użytkownika.
źródło
Ładnie wyjaśnione. Ale jedna uwaga tutaj, zamiast pisać do pliku za pomocą programu File Writer i Streaming, skorzystałem bezpośrednio z opcji logcat -f. Oto kod
Pomogło mi to w wyczyszczeniu najnowszych informacji o buforze. Korzystanie z przesyłania strumieniowego plików spowodowało, że jeden problem polegał na tym, że nie było to opróżnianie najnowszych dzienników z bufora. W każdym razie był to bardzo pomocny przewodnik. Dziękuję Ci.
źródło
Obsługa nieprzechwyconych wyjątków: jak wyjaśnił @gilm, po prostu zrób to, (kotlin):
Mam nadzieję, że to pomogło, zadziałało dla mnie ... (: y). W moim przypadku użyłem biblioteki „com.microsoft.appcenter.crashes.Crashes” do śledzenia błędów.
źródło
Możesz obsłużyć niewyłapane wyjątki za pomocą FireCrasher biblioteki i odzyskać z niej.
możesz dowiedzieć się więcej o bibliotece w tym artykule Medium
źródło