Participe do evento ⁠#Android11: apresentação de lançamento da versão Beta no dia 3 de junho.

Detectar e diagnosticar falhas

Um app para Android falha sempre que há uma saída inesperada causada por uma exceção ou um sinal não processado. Um app gravado usando Java falha se lança uma exceção não processada, representada pela classe Throwable. Um app gravado usando linguagens de código nativo falha se há um sinal não processado, como SIGSEGV, durante a execução.

Quando um app falha, o Android finaliza o processo dele e exibe uma caixa de diálogo para informar ao usuário que o app parou, conforme mostrado na figura 1.

Um app falha em um dispositivo Android

Figura 1. Um app falha em um dispositivo Android.

Um app não precisa estar em execução em primeiro plano para falhar. Qualquer componente do app, até mesmo broadcast receivers ou provedores de conteúdo em execução em segundo plano, pode causar uma falha no app. Essas falhas geralmente são confusas para os usuários, porque eles não estavam interagindo ativamente com seu app.

Se o app estiver com falhas, use as orientações desta página para diagnosticar e corrigir o problema. Para ver diretrizes sobre como diagnosticar falhas em apps criados usando linguagens de código nativo, consulte Diagnóstico de falhas nativas.

Detectar o problema

Nem sempre você sabe que seus usuários estão enfrentando um número excessivo de falhas no seu app. Se seu app já foi publicado, o recurso "Android vitals" pode ajudar você a tomar conhecimento do problema.

Android vitals

O recurso "Android vitals" pode ajudar a melhorar o desempenho do seu app, alertando pelo Play Console quando o app apresenta excesso de falhas. O "Android vitals" considera que há excesso de falhas quando um app:

  • exibe pelo menos uma falha em, no mínimo, 1,09% das sessões diárias;
  • exibe duas ou mais falhas em, pelo menos, 0,18% das sessões diárias.

Uma sessão diária refere-se a um dia em que seu app foi usado. Para ver informações sobre como o Google Play coleta dados do "Android vitals", consulte a documentação do Play Console.

Depois de descobrir que seu app está sofrendo muitas falhas, o próximo passo é diagnosticá-las.

Diagnosticar as falhas

Resolver falhas pode ser difícil. No entanto, se você conseguir identificar a causa raiz da falha, provavelmente encontrará uma solução para ela.

Existem muitas situações que podem causar uma falha no seu app. Algumas causas são óbvias, como verificar um valor nulo ou uma string vazia, mas outras são mais sutis, como passar argumentos inválidos a uma API ou até mesmo interações complexas com várias linhas de execução.

Ler um rastreamento de pilha

O primeiro passo para corrigir uma falha é identificar o local em que ela acontece. Você pode usar o rastreamento de pilha disponível nos detalhes do relatório se estiver usando o Play Console ou a saída da ferramenta logcat. Se não há um rastreamento de pilha disponível, reproduza a falha localmente, testando manualmente o app ou entrando em contato com os usuários afetados, e também enquanto estiver usando a ferramenta logcat.

O rastreamento a seguir mostra um exemplo de falha em um app de amostra:

--------- beginning of crash
    AndroidRuntime: FATAL EXCEPTION: main
    Process: com.android.developer.crashsample, PID: 3686
    java.lang.NullPointerException: crash sample
    at com.android.developer.crashsample.MainActivity$1.onClick(MainActivity.java:27)
    at android.view.View.performClick(View.java:6134)
    at android.view.View$PerformClick.run(View.java:23965)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6440)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:746)
    --------- beginning of system
    

Um rastreamento de pilha mostra duas informações essenciais para depurar uma falha:

  • o tipo de exceção lançada;
  • a seção do seu código em que a exceção é lançada.

O tipo de exceção lançada geralmente é uma dica muito forte sobre o que deu errado. Verifique se é IOException, OutOfMemoryError ou outra, e consulte a documentação sobre a classe da exceção.

A classe, o método, o número do arquivo de origem em que a exceção é lançada são mostrados na segunda linha de um rastreamento de pilha. Para cada função chamada, outra linha mostra o site de chamada anterior (chamado de "frame de pilha"). Ao percorrer a pilha e examinar o código, você pode encontrar um lugar que esteja passando um valor incorreto. Se o código não aparece no rastreamento de pilha, é provável que, em algum lugar, você tenha passado um parâmetro inválido a uma operação assíncrona. Muitas vezes, você pode descobrir o que aconteceu examinando cada linha do rastreamento de pilha, localizando as classes de API que você usou e confirmando se os parâmetros que você transmitiu estavam corretos e se você os chamou a partir de um local permitido.

Para saber mais sobre falhas em apps nativos, consulte Diagnóstico de falhas nativas.

Dicas para reproduzir uma falha

É possível que você não consiga reproduzir o problema apenas iniciando um emulador ou conectando o dispositivo ao computador. Os ambientes de desenvolvimento tendem a ter mais recursos, como largura de banda, memória e armazenamento. Use o tipo de exceção para determinar qual poderia ser o recurso escasso ou para encontrar uma correlação entre a versão do Android, o tipo de dispositivo ou a versão do seu app.

Erros de memória

Se houver um erro OutOfMemoryError, você poderá primeiro criar um emulador com baixa capacidade de memória. A figura 2 mostra as configurações do AVD Manager em que é possível controlar a quantidade de memória do dispositivo.

Configuração de memória no AVD Manager

Figura 2. Configuração de memória no AVD Manager.

Exceções de rede

Como os usuários de apps costumam entrar e sair da cobertura de rede móvel ou Wi-Fi, as exceções de rede geralmente não devem ser tratadas como erros, mas como condições operacionais normais que ocorrem inesperadamente.

Se você precisar reproduzir uma exceção de rede, como UnknownHostException, ative o modo avião quando o app tentar usar a rede.

Outra opção é reduzir a qualidade da rede no emulador, escolhendo uma emulação de velocidade de rede e/ou um atraso de rede. Você pode usar as configurações de Speed e Latency no AVD Manager ou iniciar o emulador com as sinalizações -netdelay e -netspeed, conforme mostrado no seguinte exemplo de linha de comando:

emulator -avd [your-avd-image] -netdelay 20000 -netspeed gsm
    

Esse exemplo configura um atraso de 20 segundos em todas as solicitações de rede e uma velocidade de upload e download de 14,4 Kbps. Para saber mais sobre as opções de linha de comando do emulador, consulte Iniciar o emulador pela linha de comando.

Ler com logcat

Quando concluir as etapas para reproduzir a falha, você poderá usar uma ferramenta como o logcat para conseguir mais informações.

A saída do logcat mostrará quais outras mensagens de log foram impressas, junto com outras do sistema. Não se esqueça de desativar quaisquer declarações Log extras que você tenha adicionado, porque imprimi-las desperdiça CPU e bateria enquanto o app está em execução.