Fallas

Una app de Android falla cada vez que se produce una salida inesperada a causa de una señal o excepción no controlada. Una app escrita con Java falla si muestra una excepción no controlada, representada por la clase Throwable. Una app escrita con lenguajes de código nativo falla si se produce una señal no controlada, como SIGSEGV, durante su ejecución.

Cuando falla una app, Android termina el proceso de la app y muestra un diálogo para avisarle al usuario que esta se detuvo, como se muestra en la figura 1.

Una app falla en un dispositivo Android

Figura 1: Una app falla en un dispositivo Android

No es necesario que una app se ejecute en primer plano para que falle. Cualquier componente, incluidos los receptores de transmisión o proveedores de contenido que se ejecutan en segundo plano, puede provocar que una app falle. A menudo, estas fallas confunden a los usuarios porque no estaban interactuando de manera activa con la app.

Si falla tu app, puedes usar las indicaciones que se incluyen en esta página para diagnosticar el problema y corregirlo. Si quieres obtener ayuda sobre cómo diagnosticar fallas en apps creadas con lenguajes de código nativo, consulta Cómo diagnosticar fallas por errores en código nativo.

Cómo detectar el problema

Quizás no siempre estés al tanto de que tus usuarios están experimentando una cantidad excesiva de fallas con tu app. Si ya la publicaste, Android vitals puede ayudarte a que te enteres del problema.

Android vitals

Android vitals puede ayudarte a mejorar el rendimiento de tu app. Para ello, te envía alertas, a través de Play Console, cuando tu app presenta una cantidad excesiva de fallas. Android vitals considera que una app falla de manera excesiva en los siguientes casos:

  • Cuando falla una vez, como mínimo, en al menos el 1.09% de sus sesiones diarias.
  • Cuando falla dos o más veces en al menos el 0.18% de sus sesiones diarias.

Una sesión diaria corresponde a un día en el que se usó tu app. Si deseas obtener información sobre cómo Google Play recopila datos de Android vitals, consulta la documentación de Play Console.

Una vez que se te informa que tu app falla con demasiada frecuencia, el próximo paso consiste en diagnosticar las fallas.

Cómo diagnosticar las fallas

Resolver las fallas puede ser difícil. Sin embargo, si logras identificar la causa raíz, lo más probable es que puedas encontrar una solución.

Son muchas las situaciones que pueden provocar que falle tu app. Algunas razones son obvias, como verificar un valor nulo o una string vacía, pero otras son más sutiles, como pasar argumentos no válidos a una API y las interacciones complejas con varios subprocesos.

Cómo leer un seguimiento de pila

El primer paso para corregir una falla consiste en identificar el lugar en el que sucede. Puedes usar el seguimiento de pila disponible en los detalles del informe si estás usando Play Console o el resultado de la herramienta logcat. Si no tienes un seguimiento de pila disponible, debes reproducir la falla a nivel local, ya sea probando la app de forma manual o comunicándote con los usuarios afectados, y reproduciendo la falla mientras usas la herramienta logcat.

En el seguimiento que aparece a continuación, puedes ver un ejemplo de una falla en una app de muestra:

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

En un seguimiento de pila, se muestran dos datos que son fundamentales para depurar una falla:

  • El tipo de excepción que se mostró
  • La sección del código en la que ocurre la excepción

Por lo general, el tipo de excepción que se muestra es un indicio claro de lo que salió mal. Observa si se trata de una IOException, un OutOfMemoryError o algún otro error, y encuentra la documentación sobre la clase de excepción.

La clase, el método, el archivo y el número de línea del archivo de origen en el que ocurrió la excepción se muestran en la segunda línea del seguimiento de pila. Por cada función a la que se llamó, otra línea muestra el sitio de llamada anterior (conocido como marco de pila). Si subes la pila y examinas el código, es posible que encuentres un lugar en el que se pasó un valor incorrecto. Si no se muestra tu código en el seguimiento de pila, es probable que, en algún lugar, hayas pasado un parámetro no válido a una operación asíncrona. A menudo, puedes averiguar qué sucedió si examinas cada línea del seguimiento de pila, encuentras las clases de API que usaste, y confirmas que los parámetros que pasaste eran correctos y que el lugar desde el que realizaste la llamada estaba permitido.

Si deseas obtener más información sobre las fallas en las apps nativas, consulta Cómo diagnosticar fallas por errores en código nativo.

Sugerencias para reproducir una falla

Es posible que no puedas reproducir el problema iniciando un emulador o conectando el dispositivo a la computadora. Los entornos de desarrollo tienden a contar con más recursos, como ancho de banda, memoria y almacenamiento. Usa el tipo de excepción para determinar cuál podría ser el recurso escaso o encuentra una correlación entre la versión de Android, el tipo de dispositivo o la versión de tu app.

Errores de memoria

Si experimentas un OutOfMemoryError, puedes comenzar creando un emulador con capacidad de memoria baja. En la figura 2, se muestra la configuración del Administrador de ADV que te permite controlar la cantidad de memoria en el dispositivo.

Configuración de memoria en el Administrador de AVD

Figura 2: Configuración de memoria en el Administrador de AVD

Excepciones de red

Debido a que los usuarios tienen y dejan de tener cobertura de red móvil o Wi-Fi con frecuencia, en una aplicación, las excepciones de red no se deberían tratar como errores, sino como condiciones de operación normales que suceden de forma inesperada.

Si necesitas reproducir una excepción de red, como UnknownHostException, activa el modo de avión mientras la aplicación intenta usar la red.

Otra opción consiste en reducir la calidad de la red en el emulador. Para ello, elige una emulación de velocidad o un retraso. Puedes usar las opciones de configuración de Velocidad y Latencia en el Administrador de ADV o iniciar el emulador con las marcas -netdelay y -netspeed, como se muestra en el siguiente ejemplo de la línea de comandos:

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

En este ejemplo, se define un retraso de 20 segundos en todas las solicitudes de red y una velocidad de subida y descarga de 14.4 kbps. Si deseas obtener más información sobre las opciones de la línea de comandos para el emulador, consulta Cómo iniciar el emulador desde la línea de comandos.

Cómo leer con logcat

Una vez que conoces los pasos para reproducir la falla, puedes usar una herramienta como logcat para obtener más información.

El resultado de logcat te mostrará otros mensajes de registro que imprimiste, junto con información adicional del sistema. No olvides desactivar las declaraciones Log adicionales que agregaste, ya que imprimirlas consume recursos de la CPU y la batería mientras se ejecuta tu app.