Arresti anomali del Centro app (Android)

Importante

Visual Studio App Center è previsto per il ritiro il 31 marzo 2025. Anche se è possibile continuare a usare Visual Studio App Center fino a quando non viene completamente ritirato, esistono diverse alternative consigliate che è possibile considerare la migrazione a.

Altre informazioni sulle sequenze temporali di supporto e sulle alternative.

Gli arresti anomali di App Center genereranno automaticamente un log di arresto anomalo ogni volta che l'app si arresta in modo anomalo. Il log viene prima scritto nella risorsa di archiviazione del dispositivo e quando l'utente avvia di nuovo l'app, il report di arresto anomalo verrà inviato a App Center. La raccolta di arresti anomali funziona sia per le app beta che per le app live, ad esempio quelle inviate a Google Play. I log di arresto anomalo contengono informazioni preziose per facilitare la correzione dell'arresto anomalo.

Seguire la sezione Introduzione se non è ancora stato configurato l'SDK nell'applicazione.

Generare un arresto anomalo del test

Gli arresti anomali di App Center offrono un'API per generare un arresto anomalo del test per un semplice test dell'SDK. Questa API può essere usata solo nelle compilazioni di debug e non eseguirà alcuna operazione nelle build di versione.

Crashes.generateTestCrash();
Crashes.generateTestCrash()

Ottenere altre informazioni su un arresto anomalo precedente

Gli arresti anomali di App Center hanno due API che forniscono altre informazioni in caso di arresto anomalo dell'app.

L'app ha ricevuto un avviso di memoria insufficiente nella sessione precedente?

In qualsiasi momento dopo l'avvio dell'SDK, è possibile verificare se l'app ha ricevuto un avviso di memoria nella sessione precedente:

Crashes.hasReceivedMemoryWarningInLastSession();
Crashes.hasReceivedMemoryWarningInLastSession()

Questa API è asincrona, è possibile leggere altre informazioni sulla guida alle API asincrone di App Center .

Nota

Questo metodo deve essere usato solo dopo Crashes l'avvio, verrà sempre restituito false prima dell'avvio.

Nota

In alcuni casi, un dispositivo con memoria ridotta non può inviare eventi.

L'app si è arrestata in modo anomalo nella sessione precedente?

In qualsiasi momento dopo l'avvio dell'SDK, è possibile verificare se l'app si è arrestata in modo anomalo nell'avvio precedente:

Crashes.hasCrashedInLastSession();
Crashes.hasCrashedInLastSession()

Questa API è asincrona, è possibile leggere altre informazioni sulla guida alle API asincrone di App Center .

Questo è utile nel caso in cui si vuole modificare il comportamento o l'interfaccia utente dell'app dopo un arresto anomalo. Alcuni sviluppatori hanno scelto di mostrare un'interfaccia utente aggiuntiva per scusarsi con gli utenti o vogliono entrare in contatto dopo un arresto anomalo.

Nota

Questo metodo deve essere usato solo dopo Crashes l'avvio, verrà sempre restituito false prima dell'avvio.

Dettagli sull'ultimo arresto anomalo

Se l'app si è bloccata in precedenza, è possibile ottenere informazioni dettagliate sull'ultimo arresto anomalo.

Crashes.getLastSessionCrashReport();
Crashes.getLastSessionCrashReport()

Questa API è asincrona, è possibile leggere altre informazioni sulla guida alle API asincrone di App Center .

Esistono numerosi casi d'uso per questa API, quello più comune è chi chiama questa API e implementa il proprio crashesListener personalizzato.

Nota

Questo metodo deve essere usato solo dopo Crashes l'avvio, verrà sempre restituito null prima dell'avvio.

Personalizzare l'utilizzo degli arresti anomali di App Center

Gli arresti anomali di App Center offrono callback per gli sviluppatori per eseguire azioni aggiuntive prima e quando si inviano log di arresto anomalo a App Center.

Per gestire i callback, implementare tutti i metodi nell'interfaccia o eseguire l'override della CrashesListenerAbstractCrashesListener classe e selezionare solo quelli interessati.

Usare il proprio crashesListener

Creare il proprio CrashesListener e assegnarlo come segue:

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

Se si è interessati solo alla personalizzazione di alcuni dei callback, usare invece AbstractCrashesListener :

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)

Nota

Impostare il listener prima di chiamare AppCenter.start(), poiché App Center avvia l'elaborazione si arresta in modo anomalo immediatamente dopo l'avvio.

L'arresto anomalo deve essere elaborato?

Implementare questo callback se si vuole decidere se è necessario elaborare o meno un arresto anomalo specifico. Ad esempio, potrebbe verificarsi un arresto anomalo a livello di sistema che si vuole ignorare e che non si vuole inviare a App Center.

@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
}

Se la privacy degli utenti è importante per te, potresti voler ottenere la conferma dell'utente prima di inviare un report di arresto anomalo all'App Center. L'SDK espone un callback che indica agli arresti anomali di App Center di attendere la conferma dell'utente prima di inviare eventuali report di arresto anomalo.

Se si sceglie di farlo, si è responsabili dell'acquisizione della conferma dell'utente, ad esempio tramite una richiesta di dialogo con una delle opzioni seguenti: Always Send, Send e Don't send. In base all'input, si indicherà agli arresti anomali di App Center cosa fare e l'arresto anomalo verrà quindi gestito di conseguenza.

Nota

L'SDK non visualizza una finestra di dialogo per questa operazione, l'app deve fornire la propria interfaccia utente per richiedere il consenso dell'utente.

Il callback seguente illustra come indicare all'SDK di attendere la conferma dell'utente prima di inviare arresti anomali:

@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
}

Se si restituisce true, l'app deve ottenere (usando il proprio codice) l'autorizzazione dell'utente e il messaggio dell'SDK con il risultato usando l'API seguente:

// 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)

Come esempio è possibile fare riferimento all'esempio di dialogo personalizzato.

Ottenere informazioni sullo stato di invio per un log di arresto anomalo

A volte, si vuole conoscere lo stato dell'arresto anomalo dell'app. Un caso d'uso comune è che è possibile visualizzare l'interfaccia utente che indica agli utenti che l'app invia un report di arresto anomalo o, nel caso in cui l'app si arresta in modo anomalo rapidamente dopo l'avvio, si vuole modificare il comportamento dell'app per assicurarsi che i log di arresto anomalo possano essere inviati. Gli arresti anomali di App Center hanno tre callback diversi che è possibile usare nell'app per ricevere una notifica di cosa sta succedendo:

Il callback seguente verrà richiamato prima che l'SDK invii un log di arresto anomalo

@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.
}

In caso di problemi di rete o interruzione nell'endpoint e riavvio dell'app, onBeforeSending viene attivata nuovamente dopo il riavvio del processo.

Il callback seguente verrà richiamato dopo che l'SDK ha inviato correttamente un log di arresto anomalo

@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.
}

Il callback seguente verrà richiamato se l'SDK non è riuscito a inviare un log di arresto anomalo

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

La ricezione onSendingFailed indica un errore non recuperabile, ad esempio un codice 4xx . Ad esempio, 401 significa che l'errore appSecret è errato.

Questo callback non viene attivato se si tratta di un problema di rete. In questo caso, l'SDK continua a ripetere i tentativi (e sospende anche i tentativi mentre la connessione di rete è inattiva).

Aggiungere allegati a un report di arresto anomalo

È possibile aggiungere allegati binari e di testo a un report di arresto anomalo. L'SDK li invierà insieme all'arresto anomalo in modo da poterli visualizzare nel portale di App Center. Il callback seguente verrà richiamato subito prima di inviare l'arresto anomalo archiviato dall'avvio dell'applicazione precedente. Non verrà richiamato quando si verifica l'arresto anomalo. Assicurarsi che il file allegato non sia denominato minidump.dmp come tale nome è riservato per i file minidump. Ecco un esempio di come collegare il testo e un'immagine a un arresto anomalo:

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

Nota

Il limite di dimensioni è attualmente 7 MB. Il tentativo di inviare un allegato più grande attiverà un errore.

Abilitare o disabilitare gli arresti anomali di App Center in fase di esecuzione

È possibile abilitare e disabilitare gli arresti anomali del Centro app in fase di esecuzione. Se la disabilita, l'SDK non eseguirà alcuna segnalazione di arresto anomalo per l'app.

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

Per abilitare di nuovo gli arresti anomali di App Center, usare la stessa API ma passare true come parametro.

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

Lo stato viene mantenuto nello spazio di archiviazione del dispositivo tra i lanci dell'applicazione.

Questa API è asincrona, è possibile leggere altre informazioni sulla guida alle API asincrone di App Center .

Nota

Questo metodo deve essere usato solo dopo Crashes l'avvio.

Verificare se è abilitato l'arresto anomalo di App Center

È anche possibile verificare se gli arresti anomali di App Center sono abilitati o meno:

Crashes.isEnabled();
Crashes.isEnabled()

Questa API è asincrona, è possibile leggere altre informazioni sulla guida alle API asincrone di App Center .

Nota

Questo metodo deve essere usato solo dopo Crashes l'avvio, verrà sempre restituito false prima dell'avvio.

Errori gestiti

App Center consente anche di tenere traccia degli errori usando eccezioni gestite. A tale scopo, usare il trackError metodo:

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

Un'app può facoltativamente collegare le proprietà a un report di errore gestito per fornire ulteriore contesto. Passare le proprietà come mappa delle coppie chiave/valore (solo stringhe), come illustrato nell'esempio seguente.

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

È anche possibile aggiungere allegati binari e di testo a un report di errore gestito. Passare gli allegati come Iterable illustrato nell'esempio seguente.

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

Creazione di report degli arresti anomali di NDK

Segnalazione di arresti anomali

Per ricevere report di arresto anomalo appropriati in App Center, assicurarsi di aver configurato App Center Crashes SDK seguendo le istruzioni elencate in precedenza.

Creazione della libreria del breakpad

Quindi, includere e compilare Google Breakpad seguendo le istruzioni elencate nel Google Breakpad ufficiale per Android README.

Nota

App Center SDK non raggruppa Google Breakpad per impostazione predefinita.

Collegamento del gestore eccezioni

Dopo aver incluso Google Breakpad, collegare il gestore di arresto anomalo NDK dopo 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);
        }
    }
});

Il metodo è un metodo setupNativeCrashesListener nativo che è necessario implementare in 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);
}

Dove dumpCallback viene usato per la risoluzione dei problemi:

/*
 * 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;
}

Dopo aver configurato correttamente questi metodi, l'app invia il minidump a App Center automaticamente al riavvio. Per risolvere i problemi, è possibile usare log dettagliati (AppCenter.setLogLevel(Log.VERBOSE) prima AppCenter.start) per verificare se vengono inviati minidump dopo il riavvio dell'app.

Nota

App Center usa il nome minidump.dmp riservato per gli allegati minidump. Assicurarsi di assegnare un nome diverso all'allegato, a meno che non sia un file minidump in modo da poterlo gestire correttamente.

Nota

C'è un bug noto nel breakpad che rende impossibile acquisire arresti anomali negli emulatori x86.

Simbolica

Per altre informazioni sull'elaborazione degli arresti anomali, vedere la documentazione di Diagnostica .