Bloqueo de la app — una terminación anormal en la que el programa deja de responder y se cierra. En el desarrollo móvil, los bloqueos son la principal fuente de reseñas negativas y caídas de calificación. Según Firebase (2024), los usuarios eliminan la aplicación después de uno o dos bloqueos en el 53% de los casos. Cada cierre inesperado reduce la retención en un 3–5%. Los sistemas de monitoreo como Crashlytics y Sentry ayudan a encontrar y corregir rápidamente las causas de los bloqueos antes de que afecten masivamente a los usuarios.
Puntos clave
Bloqueo — una terminación inesperada del programa causada por una situación excepcional que el código no manejó. En los sistemas operativos móviles, un bloqueo provoca el cierre inmediato de la aplicación y muestra una pantalla de “Aplicación detenida” o regresa a la pantalla de inicio.
Los bloqueos se dividen en dos grandes clases. Errores manejados — los bloques try/catch capturan la excepción, la aplicación continúa funcionando, posiblemente con pérdida de funcionalidad. Bloqueos no manejados — la excepción asciende hasta el nivel del sistema operativo y el sistema mata el proceso. El segundo tipo es especialmente peligroso porque el usuario no puede guardar datos.
Un sistema con dos millones de usuarios y una tasa de bloqueos del 0.1% pierde 2,000 usuarios en cada lanzamiento. Según Google Play Console (2024), las aplicaciones con una tasa de bloqueos superior al 1.5% son excluidas de las recomendaciones y pierden hasta el 30% del tráfico orgánico.
NullPointerException (NPE) — el rey de los bloqueos en Java/Kotlin. Intento de llamar a un método sobre un objeto null. En Kotlin, NPE es menos común gracias a la seguridad contra nulos (null safety), pero aún es posible al usar el operador !! o al interactuar con código Java. Google (2024) estima que NPE representa el 25% de todos los bloqueos de aplicaciones Android.
IndexOutOfBoundsException — acceso a un elemento de una lista con un índice inexistente. Causa frecuente: los datos llegan del servidor en un formato inesperado y la interfaz intenta mostrar una posición que no existe. Solución — siempre verifica el tamaño de la colección antes de acceder por índice.
ANR (Application Not Responding) — un problema específico de Android. El hilo de la interfaz de usuario se bloquea durante más de 5 segundos. Causas principales: solicitudes de red en el hilo principal, cálculos pesados, sincronización con la base de datos. StrictMode en Android ayuda a detectar el bloqueo del hilo de la interfaz durante el desarrollo.
OutOfMemoryError (OOM) — la aplicación superó el límite de memoria. En dispositivos móviles con 2–4 GB de RAM, OOM es un problema común al trabajar con imágenes grandes o listas infinitas sin paginación. Solución — Glide/Coil para cargar imágenes, LruCache para almacenamiento en caché, ViewHolder en RecyclerView.
Excepciones de ejecución — errores que el compilador no verifica durante la compilación. Solo aparecen cuando el código se ejecuta en un dispositivo específico con datos específicos. En Java, son RuntimeException y sus subclases: NullPointerException, IllegalArgumentException, ArithmeticException.
Errores fatales (FATAL) — no son de ejecución, sino fallos del sistema. Signal 11 (SIGSEGV) — violación de segmentación de memoria en código nativo. Signal 6 (SIGABRT) — terminación anormal provocada por la propia aplicación mediante abort(). Estos bloqueos son difíciles de diagnosticar porque el stack trace a menudo no muestra un contexto claro.
En iOS, las causas principales son NSInvalidArgumentException (nil inesperado en un parámetro) y EXC_BAD_ACCESS (acceso a memoria liberada). Swift ha reducido la cantidad de bloqueos en comparación con Objective-C, pero los errores en el runtime de ObjC y las bibliotecas C todavía provocan caídas.
Firebase Crashlytics — el estándar para aplicaciones móviles. Recopila automáticamente stack traces, agrega registros, ID de usuario y metadatos del dispositivo. Agrupa los bloqueos por firma (clase de error + línea). Alertas en tiempo real — notificaciones cuando la tasa de bloqueos supera un umbral definido (por ejemplo, >0.1% por hora).
Sentry — una alternativa con capacidades más flexibles. Permite crear contextos personalizados, agregar breadcrumbs (eventos precedentes), configurar el filtrado en la aplicación para excluir errores sin importancia. Source maps para Kotlin y Swift permiten ver el código fuente en lugar de nombres ofuscados.
Mejores prácticas para registros: envía metadatos clave antes de realizar una operación peligrosa — así el registro mostrará lo que el usuario estaba haciendo antes del bloqueo. Agrega claves personalizadas (número de versión de la API, última pantalla, tamaño de los datos de entrada). Esto convierte un stack trace inútil en información procesable.
class PaymentViewModel : ViewModel() {
fun processPayment(amount: Double) {
crashlytics.setCustomKey("last_screen", "payment")
crashlytics.setCustomKey("amount", amount)
try {
api.charge(amount)
} catch (e: Exception) {
crashlytics.recordException(e)
}
}
}
Optional binding y null safety — en Kotlin usa `?` para tipos anulables, `let` y `?:` para el manejo seguro de null. En Swift — optionals y guard let. Kotlin moderno (2024) agregó anotaciones Contract: `@ContractsDsl` permite declarar que una función no devuelve null, y el compilador lo verifica.
Manejo de errores en redes — cada solicitud de red debe manejar tiempos de espera, errores de análisis y fallos del servidor. Retrofit con tipo Result — una clase sellada que garantiza que el error será manejado. Estilo sin excepción: en lugar de try/catch, usa Result sellado para el manejo explícito de éxito y error.
Feature flags — desactiva funcionalidades problemáticas de forma remota sin lanzar una nueva versión. Si una operación del servidor provoca un bloqueo en dispositivos antiguos, el flag la desactiva para ese grupo. Firebase Remote Config permite cambiar el comportamiento de la aplicación sin publicar en la tienda.
Implementación gradual — lanza una nueva versión al 5% de la audiencia y monitorea la tasa de bloqueos. Si la tasa se mantiene por debajo del objetivo (generalmente <0.1%), expande al 25%, luego al 50% y luego al 100%. Google Play Console y App Store Connect admiten lanzamientos escalonados para la detención automática cuando se supera el umbral.
Paso 1: Clasificación — determina la gravedad: Crítico (bloqueo en >1% de los usuarios), Alto (0.1–1%), Medio (<0.1%). Para bloqueos críticos — respuesta inmediata. Para los demás — proceso estándar de corrección de errores en el sprint actual. Google Play Console clasifica automáticamente los bloqueos por el número de usuarios afectados.
Paso 2: Análisis del stack trace — abre el registro en Crashlytics, verifica la ubicación exacta del fallo. Revisa las claves personalizadas: qué pantalla, qué datos, versión del SO. Correlaciona con el último despliegue — a menudo un bloqueo es causado por un cambio reciente en el código que afectó un escenario de uso inesperado.
Paso 3: Reproducción — intenta reproducir el bloqueo en un dispositivo o emulador con parámetros similares. Si no lo logras, revisa el registro de bloqueos en busca de patrones: modelos específicos (Samsung A10), versiones de Android (API < 26), configuraciones regionales. Solución — agrega una condición defensiva que cubra el escenario.
Paso 4: Corrección y monitoreo — lanza un hotfix con prioridad. Después del lanzamiento, asegúrate de que la tasa de bloqueos para este tipo caiga a cero. Escribe una prueba de regresión que cubra el escenario del bloqueo. Sin una prueba, el mismo error puede regresar en la próxima refactorización.
Preguntas frecuentes
Tasa de bloqueos normal — inferior al 0.1% para lanzamientos de producción. Google Play recomienda mantener la tasa de bloqueos por debajo del 1.5%, pero las aplicaciones principales (YouTube, Instagram) mantienen un 0.01–0.05%. Para lanzamientos con nueva funcionalidad, se permite un aumento temporal hasta el 0.5% con una reducción posterior después de un hotfix.
Bloqueo — la aplicación termina de forma anormal. ANR (Application Not Responding) — la aplicación se congela durante más de 5 segundos pero no se cierra de forma forzada. El usuario ve un diálogo de “Aplicación no responde” y puede esperar o cerrarla. Los problemas de ANR no son menos graves que los bloqueos y también afectan la calificación en la tienda.
Diferentes dispositivos tienen diferentes versiones del SO, cantidad de memoria, versiones de bibliotecas e incluso procesadores. Ejemplo: un bloqueo en Android 6 (API 23) debido a la falta de un permiso en tiempo de ejecución puede no reproducirse en Android 12. Analiza el registro de bloqueos por filtros: versión del SO, modelo del dispositivo, cantidad de RAM. Esto indicará la especificidad del problema.
Agrega breadcrumbs personalizados en Crashlytics: registra eventos clave antes de realizar una operación. Si el bloqueo ocurre en el paso 3 de la incorporación, esto indica un problema en una pantalla específica. Símbolos de depuración (dSYM, ProGuard mapping) — cárgalos siempre en Crashlytics para ver los nombres reales de las funciones en lugar de los ofuscados.
En producción — nunca. Un bloqueo no manejado empeora la experiencia del usuario. Usa try/catch con registro de errores. En modo de depuración, bloquear es aceptable para una retroalimentación rápida al desarrollador. Assertions — para verificar invariantes que nunca deberían violarse, pero solo en compilaciones de depuración.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también