Partilhar via


App Center falha (Android)

Importante

O Visual Studio App Center foi desativado em 31 de março de 2025, exceto para os recursos de Análise e Diagnóstico, que continuarão a ter suporte até 30 de junho de 2026. Mais informações.

As falhas do App Center gerarão automaticamente um registro de falhas sempre que seu aplicativo falhar. O log é gravado primeiro no armazenamento do dispositivo e, quando o usuário iniciar o aplicativo novamente, o relatório de falhas será enviado para o App Center. A coleta de falhas funciona tanto para aplicativos beta quanto para aplicativos ao vivo, ou seja, aqueles enviados para o Google Play. Os registos de falhas contêm informações valiosas para ajudar a corrigir a falha.

Siga a seção Introdução se ainda não configurou o SDK em seu aplicativo.

Gerar uma falha de teste

O App Center Crashes fornece uma API para gerar uma falha de teste para facilitar o teste do SDK. Essa API só pode ser usada em compilações de depuração e não fará nada em compilações de versão.

Crashes.generateTestCrash();
Crashes.generateTestCrash()

Obter mais informações sobre uma falha anterior

O App Center Crashes tem duas APIs que fornecem mais informações caso seu aplicativo tenha falhado.

O aplicativo recebeu um aviso de falta de memória na sessão anterior?

A qualquer momento depois de iniciar o SDK, você pode verificar se o aplicativo recebeu um aviso de memória na sessão anterior:

Crashes.hasReceivedMemoryWarningInLastSession();
Crashes.hasReceivedMemoryWarningInLastSession()

Essa API é assíncrona, você pode ler mais sobre isso em nosso guia de APIs assíncronas do App Center .

Observação

Este método só deve ser usado depois de Crashes ter sido iniciado, ele sempre retornará false antes de começar.

Observação

Em alguns casos, um dispositivo com pouca memória não pode enviar eventos.

O aplicativo travou na sessão anterior?

A qualquer momento depois de iniciar o SDK, você pode verificar se o aplicativo falhou na inicialização anterior:

Crashes.hasCrashedInLastSession();
Crashes.hasCrashedInLastSession()

Essa API é assíncrona, você pode ler mais sobre isso em nosso guia de APIs assíncronas do App Center .

Isso é útil caso você queira ajustar o comportamento ou a interface do usuário do seu aplicativo após a ocorrência de uma falha. Alguns desenvolvedores optaram por mostrar uma interface do usuário adicional para pedir desculpas aos seus utilizadores, ou querem uma maneira de entrar em contacto após a ocorrência de uma falha.

Observação

Este método só deve ser usado depois de Crashes ter sido iniciado, ele sempre retornará false antes de começar.

Detalhes sobre o último acidente

Se o seu aplicativo travou anteriormente, você pode obter detalhes sobre a última falha.

Crashes.getLastSessionCrashReport();
Crashes.getLastSessionCrashReport()

Essa API é assíncrona, você pode ler mais sobre isso em nosso guia de APIs assíncronas do App Center .

Existem inúmeros casos de uso para essa API, o mais comum são pessoas que chamam essa API e implementam seu CrashesListener personalizado.

Observação

Este método só deve ser usado depois de Crashes ter sido iniciado, ele sempre retornará null antes de começar.

Personalize o uso do App Center Crashes

O App Center Crashes fornece callbacks para que os desenvolvedores executem ações adicionais antes e quando enviam logs de falhas para o App Center.

Para lidar com os callbacks, implemente todos os CrashesListener métodos na interface ou substitua a AbstractCrashesListener classe e escolha apenas aqueles nos quais tenha interesse.

Utilize o seu próprio CrashesListener

Crie seu próprio CrashesListener e atribua-o assim:

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

Caso esteja interessado apenas em personalizar alguns dos callbacks, use o AbstractCrashesListener em vez disso.

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)

Observação

Defina o ouvinte antes de ligar AppCenter.start(), uma vez que o App Center começa a processar falhas imediatamente após o início.

O acidente deve ser processado?

Implemente este callback se quiser decidir se um crash específico precisa ser processado ou não. Por exemplo, pode haver uma falha no nível do sistema que você gostaria de ignorar e que não deseja enviar para o 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 a privacidade do usuário for importante para você, convém obter a confirmação do usuário antes de enviar um relatório de falhas para o App Center. O SDK expõe um callback que indica ao App Center Crashes para aguardar a confirmação do utilizador antes de enviar qualquer relatório de falhas.

Se você optar por fazê-lo, você é responsável por obter a confirmação do usuário, por exemplo, através de um prompt de diálogo com uma das seguintes opções: Sempre enviar, Enviar e Não enviar. Com base na entrada, você informará ao App Center Crashes o que fazer e a falha será tratada de acordo.

Observação

O SDK não exibe uma caixa de diálogo para isso, o aplicativo deve fornecer sua própria interface do usuário para solicitar o consentimento do usuário.

O seguinte callback mostra como instruir o SDK a esperar pela confirmação do usuário antes de enviar crashes:

@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 você retornar true, seu aplicativo deverá obter (usando seu próprio código) a permissão do usuário e enviar uma mensagem ao SDK com o resultado usando a seguinte 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)

Como exemplo, você pode consultar nosso exemplo de diálogo personalizado.

Obter informações sobre o estado de envio de um registo de falhas

Às vezes, você quer saber o status da falha do seu aplicativo. Um caso de uso comum é que você pode querer mostrar a interface do usuário que informa aos usuários que seu aplicativo está enviando um relatório de falhas ou, caso seu aplicativo esteja falhando rapidamente após a inicialização, você deseja ajustar o comportamento do aplicativo para garantir que os logs de falhas possam ser enviados. O App Center Crashes tem três retornos de chamada diferentes que pode utilizar na sua aplicação para ser notificado do que está a acontecer.

O seguinte callback será invocado antes que o SDK envie um registo de falhas

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

No caso de termos problemas de rede ou uma interrupção no ponto de extremidade, e você reiniciar o aplicativo, onBeforeSending é acionado novamente após a reinicialização do processo.

A função de retorno seguinte será invocada depois do SDK enviar com sucesso um relatório de falhas.

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

O seguinte callback será invocado se o SDK não conseguir enviar um registo de falhas.

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

Receber onSendingFailed significa que ocorreu um erro não recuperável, como ocorreu um código 4xx . Por exemplo, 401 significa que o appSecret está errado.

Esse retorno de chamada não é acionado se for um problema de rede. Nesse caso, o SDK continua tentando novamente (e também pausa novas tentativas enquanto a conexão de rede está inativa).

Adicionar anexos a um relatório de falhas

Você pode adicionar anexos binários e de texto a um relatório de falhas. O SDK irá enviá-los juntamente com o crash para que os possa ver no portal do App Center. O seguinte callback será invocado imediatamente antes de enviar a falha armazenada de lançamentos anteriores do aplicativo. Ele não será invocado quando a falha acontecer. Certifique-se de que o arquivo anexo não tenha nome minidump.dmp , pois esse nome está reservado para arquivos minidump. Eis um exemplo de como anexar texto e uma imagem a um crash:

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

Observação

Atualmente, o limite de tamanho é de 7 MB. A tentativa de enviar um anexo maior desencadeará um erro.

Ativar ou desativar falhas do App Center em tempo de execução

Você pode habilitar e desabilitar a funcionalidade Crashes do App Center em tempo de execução. Se você desativá-lo, o SDK não fará nenhum relatório de falhas para o aplicativo.

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

Para habilitar as falhas do App Center novamente, use a mesma API, mas passe true como parâmetro.

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

O estado é persistido no armazenamento do dispositivo em todas as inicializações de aplicativos.

Essa API é assíncrona, você pode ler mais sobre isso em nosso guia de APIs assíncronas do App Center .

Observação

Este método só deve ser utilizado depois de Crashes ter sido iniciado.

Verifique se o App Center Crashes está ativado

Você também pode verificar se o App Center Crashes está ativado ou não:

Crashes.isEnabled();
Crashes.isEnabled()

Essa API é assíncrona, você pode ler mais sobre isso em nosso guia de APIs assíncronas do App Center .

Observação

Este método só deve ser usado depois de Crashes ter sido iniciado, ele sempre retornará false antes de começar.

Erros tratados

O App Center também permite rastrear erros usando exceções manipuladas. Para fazer isso, use o trackError método:

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

Opcionalmente, um aplicativo pode anexar propriedades a um relatório de erros manipulado para fornecer mais contexto. Passe as propriedades como um mapa de pares chave/valor (somente strings), conforme mostrado no exemplo abaixo.

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

Opcionalmente, você também pode adicionar anexos binários e de texto a um relatório de erro manipulado. Passe os anexos como Iterable conforme mostrado no exemplo abaixo.

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

Relatando falhas de NDK

Comunicar falhas

Para receber relatórios de falhas adequados no App Center, primeiro certifique-se de ter o SDK de falhas do App Center configurado seguindo as instruções listadas acima.

Construção da biblioteca Breakpad

Em seguida, inclua e compile o Google Breakpad seguindo as instruções listadas no Google Breakpad oficial para Android README.

Observação

O SDK do App Center não agrupa o Google Breakpad por padrão.

Anexando o manipulador de exceção

Depois de ter incluído o Google Breakpad, anexe o NDK Crash Handler após 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);
        }
    }
});

O método setupNativeCrashesListener é um método nativo que você deve implementar em 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);
}

Onde dumpCallback é usado para solução de problemas:

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

Depois que esses métodos estiverem configurados corretamente, o aplicativo envia o minidump para o App Center automaticamente após a reinicialização. Para solucionar problemas, pode usar logs detalhados (AppCenter.setLogLevel(Log.VERBOSE) antes AppCenter.start) para verificar se os minidumps são enviados após o reinício da aplicação.

Observação

O App Center usa o nome minidump.dmp reservado para anexos de minidump. Certifique-se de dar ao seu anexo um nome diferente, a menos que seja um arquivo minidump para que possamos manipulá-lo corretamente.

Observação

Há um bug conhecido no breakpad que torna impossível capturar falhas em emuladores x86.

Simbologia

Consulte a documentação de Diagnóstico para obter mais informações sobre o processamento de falhas.