Awarie centrum aplikacji (Android)

Ważne

Program Visual Studio App Center ma zostać wycofany 31 marca 2025 r. Mimo że możesz nadal używać programu Visual Studio App Center do momentu jej pełnego wycofania, istnieje kilka zalecanych alternatyw, do których można rozważyć migrację.

Dowiedz się więcej o osiach czasu pomocy technicznej i alternatywach.

Awarie centrum aplikacji automatycznie wygenerują dziennik awarii za każdym razem, gdy aplikacja ulegnie awarii. Dziennik jest najpierw zapisywany w magazynie urządzenia, a gdy użytkownik ponownie uruchomi aplikację, raport o awarii zostanie wysłany do Centrum aplikacji. Zbieranie awarii działa zarówno w przypadku aplikacji beta, jak i na żywo, tj. przesłanych do sklepu Google Play. Dzienniki awarii zawierają cenne informacje ułatwiające naprawienie awarii.

Jeśli zestaw SDK nie został jeszcze skonfigurowany w aplikacji, postępuj zgodnie z sekcją Wprowadzenie.

Generowanie awarii testowej

Usługa App Center Crash udostępnia interfejs API umożliwiający wygenerowanie awarii testowej w celu łatwego testowania zestawu SDK. Ten interfejs API może być używany tylko w kompilacjach debugowania i nie wykonuje żadnych czynności w kompilacjach wydania.

Crashes.generateTestCrash();
Crashes.generateTestCrash()

Uzyskaj więcej informacji o poprzedniej awarii

Usługa App Center Crash ma dwa interfejsy API, które zapewniają więcej informacji na wypadek awarii aplikacji.

Czy w poprzedniej sesji aplikacja otrzymała ostrzeżenie o niskiej ilości pamięci?

W dowolnym momencie po uruchomieniu zestawu SDK możesz sprawdzić, czy aplikacja otrzymała ostrzeżenie o pamięci w poprzedniej sesji:

Crashes.hasReceivedMemoryWarningInLastSession();
Crashes.hasReceivedMemoryWarningInLastSession()

Ten interfejs API jest asynchroniczny. Więcej informacji na ten temat można przeczytać w przewodniku asynchronicznych interfejsów API centrum aplikacji .

Uwaga

Ta metoda musi być używana tylko po Crashes rozpoczęciu. Będzie ona zawsze zwracana false przed rozpoczęciem.

Uwaga

W niektórych przypadkach urządzenie z małą ilością pamięci nie może wysyłać zdarzeń.

Czy aplikacja uległa awarii w poprzedniej sesji?

W dowolnym momencie po uruchomieniu zestawu SDK możesz sprawdzić, czy aplikacja uległa awarii w poprzednim uruchomieniu:

Crashes.hasCrashedInLastSession();
Crashes.hasCrashedInLastSession()

Ten interfejs API jest asynchroniczny. Więcej informacji na ten temat można przeczytać w przewodniku asynchronicznych interfejsów API centrum aplikacji .

Jest to przydatne w przypadku, gdy chcesz dostosować zachowanie lub interfejs użytkownika aplikacji po wystąpieniu awarii. Niektórzy deweloperzy zdecydowali się pokazać dodatkowy interfejs użytkownika, aby przeprosić swoich użytkowników lub chcieć skontaktować się po wystąpieniu awarii.

Uwaga

Ta metoda musi być używana tylko po Crashes rozpoczęciu. Będzie ona zawsze zwracana false przed rozpoczęciem.

Szczegóły dotyczące ostatniej awarii

Jeśli aplikacja uległa awarii wcześniej, możesz uzyskać szczegółowe informacje o ostatniej awarii.

Crashes.getLastSessionCrashReport();
Crashes.getLastSessionCrashReport()

Ten interfejs API jest asynchroniczny. Więcej informacji na ten temat można przeczytać w przewodniku asynchronicznych interfejsów API centrum aplikacji .

W przypadku tego interfejsu API istnieje wiele przypadków użycia. Najczęściej są to osoby, które nazywają ten interfejs API i implementują niestandardowy element CrashListener.

Uwaga

Ta metoda musi być używana tylko po Crashes rozpoczęciu. Będzie ona zawsze zwracana null przed rozpoczęciem.

Dostosowywanie użycia awarii centrum aplikacji

Usługa App Center Crash udostępnia wywołania zwrotne dla deweloperów w celu wykonywania dodatkowych akcji przed i podczas wysyłania dzienników awarii do centrum aplikacji.

Aby obsłużyć wywołania zwrotne, zaimplementuj wszystkie metody w interfejsie CrashesListener lub przesłoń AbstractCrashesListener klasę i wybierz tylko te, które cię interesują.

Korzystanie z własnego narzędzia CrashListener

Utwórz własny element CrashListener i przypisz go w następujący sposób:

CrashesListener customListener = new CrashesListener() {
    // Implement all callbacks here.
};
Crashes.setListener(customListener);
val customListener = object : CrashesListener {
    // Implement all callbacks here.
}
Crashes.setListener(customListener)

Jeśli interesuje Cię tylko dostosowywanie niektórych wywołań zwrotnych, użyj polecenia AbstractCrashesListener zamiast tego:

AbstractCrashesListener customListener = new AbstractCrashesListener() {
    // Implement any callback here as required.
};
Crashes.setListener(customListener);
val customListener = object : AbstractCrashesListener() {
    // Implement any callback here as required.
}
Crashes.setListener(customListener)

Uwaga

Ustaw odbiornik przed wywołaniem metody AppCenter.start(), ponieważ usługa App Center rozpoczyna przetwarzanie awarii natychmiast po uruchomieniu.

Czy awaria powinna zostać przetworzona?

Zaimplementuj to wywołanie zwrotne, jeśli chcesz zdecydować, czy należy przetworzyć konkretną awarię, czy nie. Na przykład może wystąpić awaria na poziomie systemu, którą chcesz zignorować i że nie chcesz wysyłać do centrum aplikacji.

@Override
public boolean shouldProcess(ErrorReport report) {
    return true; // return true if the crash report should be processed, otherwise false.
}
override fun shouldProcess(report: ErrorReport?): Boolean {
    return true
}

Jeśli prywatność użytkownika jest dla Ciebie ważna, możesz uzyskać potwierdzenie użytkownika przed wysłaniem raportu o awarii do Centrum aplikacji. Zestaw SDK uwidacznia wywołanie zwrotne, które informuje usługę App Center Crash o oczekiwaniu na potwierdzenie użytkownika przed wysłaniem raportów o awarii.

Jeśli zdecydujesz się to zrobić, odpowiadasz za uzyskanie potwierdzenia użytkownika, np. za pośrednictwem monitu dialogowego z jedną z następujących opcji: Zawsze wysyłaj, Wysyłaj i nie wysyłaj. Na podstawie danych wejściowych poinformujesz centrum aplikacji o awarii, co należy zrobić, a awaria zostanie odpowiednio obsłużona.

Uwaga

Zestaw SDK nie wyświetla okna dialogowego. Aplikacja musi podać własny interfejs użytkownika, aby poprosić o zgodę użytkownika.

Poniższe wywołanie zwrotne pokazuje, jak poinformować zestaw SDK o oczekiwaniu na potwierdzenie użytkownika przed wysłaniem awarii:

@Override
public boolean shouldAwaitUserConfirmation() {

    // Build your own UI to ask for user consent here. SDK doesn't provide one by default.

    // Return true if you built a UI for user consent and are waiting for user input on that custom UI, otherwise false.
    return true;
}
override fun shouldAwaitUserConfirmation(): Boolean {
    return true
}

Jeśli zwrócisz truepolecenie , aplikacja musi uzyskać (przy użyciu własnego kodu) uprawnienie użytkownika i wysłać komunikat do zestawu SDK z wynikiem przy użyciu następującego interfejsu API:

// Depending on the user's choice, call Crashes.notifyUserConfirmation() with the right value.
Crashes.notifyUserConfirmation(Crashes.DONT_SEND);
Crashes.notifyUserConfirmation(Crashes.SEND);
Crashes.notifyUserConfirmation(Crashes.ALWAYS_SEND);
Crashes.notifyUserConfirmation(Crashes.DONT_SEND)
Crashes.notifyUserConfirmation(Crashes.SEND)
Crashes.notifyUserConfirmation(Crashes.ALWAYS_SEND)

Jako przykład można odwoływać się do naszego przykładu niestandardowego okna dialogowego.

Uzyskiwanie informacji o stanie wysyłania dziennika awarii

Czasami chcesz znać stan awarii aplikacji. Typowy przypadek użycia polega na tym, że możesz pokazać interfejs użytkownika, który informuje użytkowników, że aplikacja przesyła raport o awarii lub w przypadku, gdy aplikacja ulega awarii szybko po uruchomieniu, chcesz dostosować zachowanie aplikacji, aby upewnić się, że dzienniki awarii można przesłać. Usługa App Center Crash ma trzy różne wywołania zwrotne, których można użyć w aplikacji, aby otrzymywać powiadomienia o tym, co się dzieje:

Następujące wywołanie zwrotne zostanie wywołane przed wysłaniem dziennika awarii przez zestaw SDK

@Override
public void onBeforeSending(ErrorReport errorReport) {
    // Your code, e.g. to present a custom UI.
}
override fun onBeforeSending(report: ErrorReport?) {
    // Your code, e.g. to present a custom UI.
}

W przypadku wystąpienia problemów z siecią lub awarii punktu końcowego i ponowne uruchomienie aplikacji onBeforeSending zostanie ponownie wyzwolone po ponownym uruchomieniu procesu.

Następujące wywołanie zwrotne zostanie wywołane po pomyślnym wysłaniu dziennika awarii zestawu SDK

@Override
public void onSendingSucceeded(ErrorReport report) {
    // Your code, e.g. to hide the custom UI.
}
override fun onSendingSucceeded(report: ErrorReport?) {
    // Your code, e.g. to hide the custom UI.
}

Następujące wywołanie zwrotne zostanie wywołane, jeśli zestaw SDK nie może wysłać dziennika awarii

@Override
public void onSendingFailed(ErrorReport report, Exception e) {
    // Your code goes here.
}
override fun onSendingFailed(report: ErrorReport?, e: Exception?) {
    // Your code goes here.
}

Odbieranie onSendingFailed oznacza, że wystąpił błąd niemożliwy do odzyskania, taki jak kod 4xx . Na przykład 401 oznacza, że wartość jest nieprawidłowa appSecret .

To wywołanie zwrotne nie jest wyzwalane, jeśli jest to problem z siecią. W takim przypadku zestaw SDK ponawia próbę (a także wstrzymuje ponawianie próby, gdy połączenie sieciowe nie działa).

Dodawanie załączników do raportu o awarii

Możesz dodać załączniki binarne i tekstowe do raportu o awarii. Zestaw SDK wyśle je wraz z awarią, aby można było je zobaczyć w portalu centrum aplikacji. Następujące wywołanie zwrotne zostanie wywołane bezpośrednio przed wysłaniem przechowywanej awarii z poprzednich uruchomień aplikacji. Nie będzie wywoływana, gdy wystąpi awaria. Upewnij się, że plik załącznika nie ma nazwy, minidump.dmp ponieważ ta nazwa jest zarezerwowana dla plików minidump. Oto przykład dołączania tekstu i obrazu do awarii:

@Override
public Iterable<ErrorAttachmentLog> getErrorAttachments(ErrorReport report) {

    // Attach some text.
    ErrorAttachmentLog textLog = ErrorAttachmentLog.attachmentWithText("This is a text attachment.", "text.txt");

    // Attach binary data.
    byte[] binaryData = getYourBinary();
    ErrorAttachmentLog binaryLog = ErrorAttachmentLog.attachmentWithBinary(binaryData, "your_filename.jpeg", "image/jpeg");

    // Return attachments as list.
    return Arrays.asList(textLog, binaryLog);
}
override fun getErrorAttachments(report: ErrorReport?): MutableIterable<ErrorAttachmentLog> {

    // Attach some text.
    val textLog = ErrorAttachmentLog.attachmentWithText("This is a text attachment.", "text.txt")

    // Attach binary data.
    val binaryData = getYourBinary()
    val binaryLog = ErrorAttachmentLog.attachmentWithBinary(binaryData, "your_filename.jpeg", "image/jpeg")

    // Return attachments as list.
    return listOf(textLog, binaryLog)
}

Uwaga

Limit rozmiaru wynosi obecnie 7 MB. Próba wysłania większego załącznika spowoduje wyzwolenie błędu.

Włączanie lub wyłączanie awarii usługi App Center w czasie wykonywania

Możesz włączyć i wyłączyć awarie usługi App Center w czasie wykonywania. Jeśli ją wyłączysz, zestaw SDK nie będzie wykonywać żadnych raportów o awarii dla aplikacji.

Crashes.setEnabled(false);
Crashes.setEnabled(false)

Aby ponownie włączyć awarie usługi App Center, użyj tego samego interfejsu API, ale przekaż true go jako parametr.

Crashes.setEnabled(true);
Crashes.setEnabled(true)

Stan jest utrwalany w magazynie urządzenia w ramach uruchamiania aplikacji.

Ten interfejs API jest asynchroniczny. Więcej informacji na ten temat można przeczytać w przewodniku asynchronicznych interfejsów API centrum aplikacji .

Uwaga

Ta metoda musi być używana tylko po Crashes rozpoczęciu.

Sprawdzanie, czy w centrum aplikacji jest włączona awaria

Możesz również sprawdzić, czy usługa App Center Ulega awarii jest włączona, czy nie:

Crashes.isEnabled();
Crashes.isEnabled()

Ten interfejs API jest asynchroniczny. Więcej informacji na ten temat można przeczytać w przewodniku asynchronicznych interfejsów API centrum aplikacji .

Uwaga

Ta metoda musi być używana tylko po Crashes uruchomieniu. Zawsze będzie ona zwracana false przed rozpoczęciem.

Obsługiwane błędy

Usługa App Center umożliwia również śledzenie błędów przy użyciu obsługiwanych wyjątków. W tym celu użyj trackError metody :

try {
    // your code goes here.
} catch (Exception exception) {
    Crashes.trackError(exception);
}
try {
    // your code goes here.
} catch (exception: Exception) {
    Crashes.trackError(exception)
}

Aplikacja może opcjonalnie dołączać właściwości do obsłużonego raportu o błędach w celu zapewnienia dalszego kontekstu. Przekaż właściwości jako mapę par klucz/wartość (tylko ciągi), jak pokazano w poniższym przykładzie.

try {
    // your code goes here.
} catch (Exception exception) {
    Map<String, String> properties = new HashMap<String, String>() {{
        put("Category", "Music");
        put("Wifi", "On");
    }};
    Crashes.trackError(exception, properties, null);
}
try {
    // your code goes here.
} catch (exception: Exception) {
    val properties = mapOf("Category" to "Music", "Wifi" to "On")
    Crashes.trackError(exception, properties, null)
}

Opcjonalnie możesz również dodać załączniki binarne i tekstowe do obsłużonego raportu o błędach. Przekaż załączniki jako element Iterable , jak pokazano w poniższym przykładzie.

try {
    // your code goes here.
} catch (Exception exception) {

    // Attach some text.
    ErrorAttachmentLog textLog = ErrorAttachmentLog.attachmentWithText("This is a text attachment.", "text.txt");

    // Attach binary data.
    byte[] binaryData = getYourBinary();
    ErrorAttachmentLog binaryLog = ErrorAttachmentLog.attachmentWithBinary(binaryData, "your_filename.jpeg", "image/jpeg");

    // Track an exception with attachments.
    Crashes.trackError(exception, null, Arrays.asList(textLog, binaryLog));
}
try {
    // your code goes here.
} catch (exception: Exception) {

    // Attach some text.
    val textLog = ErrorAttachmentLog.attachmentWithText("This is a text attachment.", "text.txt")

    // Attach binary data.
    val binaryData = getYourBinary()
    val binaryLog = ErrorAttachmentLog.attachmentWithBinary(binaryData, "your_filename.jpeg", "image/jpeg")

    // Track an exception with attachments.
    Crashes.trackError(exception, null, listOf(textLog, binaryLog))
}

Raportowanie awarii NDK

Raportowanie awarii

Aby otrzymywać odpowiednie raporty dotyczące awarii w centrum aplikacji, najpierw upewnij się, że masz skonfigurowany zestaw SDK awarii centrum aplikacji, postępując zgodnie z instrukcjami wymienionymi powyżej.

Kompilowanie biblioteki breakpad

Następnie dołącz i skompiluj google Breakpad, postępując zgodnie z instrukcjami wymienionymi w oficjalnym Google Breakpad dla systemu Android README.

Uwaga

Zestaw SDK usługi App Center domyślnie nie pakuje aplikacji Google Breakpad.

Dołączanie programu obsługi wyjątków

Po dołączeniu aplikacji Google Breakpad dołącz program obsługi awarii NDK po AppCenter.start:

// Attach NDK Crash Handler after SDK is initialized.
Crashes.getMinidumpDirectory().thenAccept(new AppCenterConsumer<String>() {
    @Override
    public void accept(String path) {

        // Path is null when Crashes is disabled.
        if (path != null) {
            setupNativeCrashesListener(path);
        }
    }
});

Metoda setupNativeCrashesListener jest metodą natywną, którą należy zaimplementować w języku C/C++:

#include "google-breakpad/src/client/linux/handler/exception_handler.h"
#include "google-breakpad/src/client/linux/handler/minidump_descriptor.h"

void Java_com_microsoft_your_package_YourActivity_setupNativeCrashesListener(
        JNIEnv *env, jobject, jstring path) {
    const char *dumpPath = (char *) env->GetStringUTFChars(path, NULL);
    google_breakpad::MinidumpDescriptor descriptor(dumpPath);
    new google_breakpad::ExceptionHandler(descriptor, NULL, dumpCallback, NULL, true, -1);
    env->ReleaseStringUTFChars(path, dumpPath);
}

Gdzie dumpCallback służy do rozwiązywania problemów:

/*
 * Triggered automatically after an attempt to write a minidump file to the breakpad folder.
 */
bool dumpCallback(const google_breakpad::MinidumpDescriptor &descriptor,
                  void *context,
                  bool succeeded) {

    // Allow system to log the native stack trace.
    __android_log_print(ANDROID_LOG_INFO, "YourLogTag",
                        "Wrote breakpad minidump at %s succeeded=%d\n", descriptor.path(),
                        succeeded);
    return false;
}

Po poprawnym skonfigurowaniu tych metod aplikacja automatycznie wysyła minidump do Centrum aplikacji po ponownym uruchomieniu. Aby rozwiązać problemy, możesz użyć pełnych dzienników (AppCenter.setLogLevel(Log.VERBOSE) przed AppCenter.start) w celu sprawdzenia, czy minidumps są wysyłane po ponownym uruchomieniu aplikacji.

Uwaga

Usługa App Center używa nazwy minidump.dmp zarezerwowanej dla załączników minidump. Pamiętaj, aby nadać załącznikowi inną nazwę, chyba że jest to plik minidump, abyśmy mogli go poprawnie obsłużyć.

Uwaga

Istnieje znana usterka w breakpad, która uniemożliwia przechwytywanie awarii na emulatorach x86.

Symboliczne

Aby uzyskać więcej informacji na temat przetwarzania awarii, zobacz dokumentację diagnostyki .