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, por exemplo, 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.

Falha de um app em um dispositivo Android

Figura 1. Falha de um app em um dispositivo Android.

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

Se o app estiver apresentando falhas, use as diretrizes 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 grande de falhas no seu app. Se você já publicou o app, o recurso "Android vitals" pode ajudar você a ficar sabendo do problema.

Android vitals

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

  • exibe pelo menos uma falha em pelo menos 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á tendo 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.

Muitas situações 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 transmitir argumentos inválidos a uma API ou até mesmo interações complexas com várias linhas de execução.

Ler um stack trace

O primeiro passo para corrigir uma falha é identificar o lugar em que ela acontece. Você pode usar o stack trace disponível nos detalhes do relatório se estiver usando o Play Console ou a saída da ferramenta Logcat. Se não houver um stack trace disponível, reproduza a falha localmente testando o app de forma manual ou entrando em contato com os usuários afetados, e a reproduza enquanto estiver usando a ferramenta Logcat.

O trace 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 stack trace mostra duas informações essenciais para depurar uma falha:

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

O tipo de exceção lançada geralmente é uma pista muito forte sobre o que deu errado. Veja se é uma IOException, um OutOfMemoryError ou algo mais e encontre 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 stack trace. Para cada função chamada, outra linha mostra o local da chamada anterior (chamado "frame de pilha"). Subindo a pilha e examinando o código, você pode encontrar um lugar que esteja transmitindo um valor incorreto. Se o código não aparece no stack trace, é provável que, em algum lugar, você tenha transmitido um parâmetro inválido a uma operação assíncrona. Muitas vezes, você pode descobrir o que aconteceu examinando cada linha do stack trace, localizando quaisquer classes de API que você usou e confirmando que os parâmetros que você transmitiu estavam corretos e que você os chamou a partir de um local permitido.

Para saber mais sobre falhas em aplicativos 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 você tiver um OutOfMemoryError, poderá criar um emulador com baixa capacidade de memória para começar. A Figura 2 mostra as configurações do AVD Manager em que você pode controlar a quantidade de memória no dispositivo.

Configuração de memória do AVD Manager

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

Exceções de rede

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

Se você precisar reproduzir uma exceção de rede, como UnknownHostException, tente ativar o modo avião enquanto o aplicativo tenta usar a rede.

Outra opção é reduzir a qualidade da rede no emulador escolhendo uma emulação de velocidade e/ou um atraso de rede. Você pode usar as configurações de Velocidade e Latência 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 define 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 você tiver as etapas para reproduzir a falha, poderá usar uma ferramenta como o Logcat para ver mais informações.

A saída do Logcat mostrará quais outras mensagens de registro foram impressas, junto a 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.