StrictMode: qué es, modo de reglas estrictas y depuración en Android

Autor: IT Sectr Publicado: 2026-03-31 Tiempo de lectura: 8 min

StrictMode es una herramienta de desarrollador integrada en el SDK de Android que detecta e informa en tiempo real sobre operaciones accidentales de E/S y llamadas de red en el hilo principal de la aplicación. No corrige errores, sino que actúa como detector: lanza excepciones o escribe en LogCat cuando se violan las políticas configuradas. Según Google, 2024, una configuración adecuada de StrictMode permite detectar hasta el 80% de los problemas de rendimiento antes del lanzamiento de la aplicación.

Puntos clave

  • StrictMode — un detector de violaciones de rendimiento en el hilo principal de Android
  • Políticas de disco (disk_read, disk_write) y red (network) forman el conjunto básico de comprobaciones
  • La herramienta no soluciona problemas, sino que notifica sobre ellos a través de LogCat, un diálogo o un crash
  • La configuración se realiza en Application.onCreate usando setThreadPolicy + setVmPolicy
  • Modos de penalización: lanzamiento de excepción (death), registro, notificación en dropbox

Qué es StrictMode

StrictMode es una API incluida en el SDK de Android desde el nivel de API 9 (Android 2.3 Gingerbread). Su tarea es detectar en tiempo de ejecución la ejecución accidental de operaciones pesadas en el hilo principal (UI) que podrían bloquear el renderizado de la interfaz. El hilo principal maneja el procesamiento de la entrada del usuario, el cálculo del diseño y el renderizado: cualquier bloqueo de más de 16 ms provoca la pérdida de un fotograma.

Filosofía de la herramienta

StrictMode sigue el principio de “fallar rápido”: detectar el problema lo antes posible, idealmente en el momento de su primera aparición. En lugar de esperar las quejas de los usuarios sobre ralentizaciones, el desarrollador recibe una señal (registros, diálogo o crash) directamente en la etapa de desarrollo. La herramienta no requiere bibliotecas adicionales ni configuración de Gradle: basta con unas pocas líneas de código en Application.onCreate, y funciona automáticamente en todos los dispositivos.

Público objetivo

StrictMode está diseñado para todos los desarrolladores de Android, independientemente de su experiencia. Para los principiantes, ayuda a formar buenos hábitos (no hacer solicitudes de red en el hilo de UI); para los experimentados, automatiza el control de calidad en el pipeline de CI/CD. Los proyectos grandes (Google, Uber, Spotify) incluyen StrictMode en las compilaciones de depuración con penaltyDeath, y lo desactivan en las compilaciones de lanzamiento mediante la comprobación de BuildConfig.DEBUG.

Cómo funciona StrictMode

StrictMode intercepta las llamadas al sistema que podrían bloquear el hilo y las compara con el conjunto de políticas activas. Si una llamada coincide con una política y se ejecuta en el hilo principal, StrictMode aplica la penalización especificada. El mecanismo de intercepción se implementa mediante un gancho dentro del proceso: no utiliza reflexión y opera con una sobrecarga mínima.

Mecanismo de detección

Cuando se activa la política de StrictMode, inyecta su manejador en los puntos de entrada de las llamadas al sistema (FileInputStream, FileOutputStream, Socket, URLConnection). Cuando la aplicación llama, por ejemplo, a URLConnection.openStream en el hilo principal, StrictMode comprueba el hilo actual: si es el hilo principal, la herramienta se activa. En Android 6.0+, el mecanismo se mejora: las llamadas de red en el hilo principal generan NetworkOnMainThreadException incluso sin StrictMode, pero StrictMode también permite controlar la E/S de disco.

Penalización

Cada política puede tener su propio tipo de penalización o combinación: penaltyLog — escribe en LogCat con un stack trace, penaltyDialog — muestra un diálogo al usuario (solo en depuración), penaltyDeath — lanza una excepción y causa un crash de la aplicación, penaltyDropBox — guarda datos en DropBoxManager para análisis posterior. Para pipelines de CI/CD, se recomienda penaltyDeath — garantiza que ninguna fusión con violaciones pase desapercibida.

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()
                    .penaltyLog()
                    .penaltyDeath()
                    .build()
            )
        }
    }
}

Políticas de StrictMode

StrictMode divide las políticas en dos niveles: ThreadPolicy (a nivel de hilo — lo que no se puede hacer en el hilo principal) y VmPolicy (máquina virtual — fugas de memoria y recursos). Ambos niveles se configuran de forma independiente y funcionan en paralelo.

ThreadPolicy: Disco y Red

A nivel de hilo, StrictMode controla cuatro tipos de violaciones: lecturas de disco (detectDiskReads), escrituras en disco (detectDiskWrites), operaciones de red (detectNetwork) y llamadas lentas personalizadas (detectCustomSlowCalls). disk_read se activa ante cualquier lectura de SharedPreferences, SQLite o archivos en el hilo principal. network se activa ante solicitudes HTTP, WebSocket y conexiones Socket. En Android 11+, se agregó detectUnbufferedIO para detectar E/S sin búfer.

VmPolicy: Fugas de Memoria

VmPolicy controla las fugas a nivel de la máquina virtual ART: detectActivityLeaks (actividades que no fueron destruidas), detectLeakedClosableObjects (Cursor, Stream, Socket no cerrados), detectLeakedRegistrationObjects (BroadcastReceiver, ServiceConnection no registrados). Si VmPolicy detecta que una Activity fue creada pero no destruida después de llamar a onDestroy, muestra un stack trace completo: ahorra horas de depuración de fugas de memoria.

PolíticaNivelLo que detecta
detectDiskReadsThreadLectura de SharedPrefs, SQLite, archivos en el hilo de UI
detectDiskWritesThreadEscritura en SharedPrefs, SQLite, archivos en el hilo de UI
detectNetworkThreadCualquier operación de red en el hilo de UI
detectActivityLeaksVMActivities que sobreviven a onDestroy
detectLeakedClosableObjectsVMCursor, Stream, Socket no cerrados

Llamadas lentas personalizadas

A través de detectCustomSlowCalls, puedes marcar tus propios métodos como “sospechosos” y recibir una advertencia cuando se supere un umbral especificado. Por ejemplo, si tu método loadUserProfile() normalmente toma 5 ms pero a veces toma 200 ms — envuélvelo en StrictMode.noteSlowCall(“loadUserProfile”). Si la duración supera el umbral (por defecto 2000 ms), StrictMode generará una penalización. El umbral se configura mediante setSlowCallDurationThreshold.

Cómo configurar StrictMode

La configuración básica de StrictMode toma 10 líneas de código y se realiza en el método onCreate de una clase Application personalizada. La regla principal: StrictMode se activa solo en compilaciones de depuración — en compilaciones de lanzamiento ralentiza la aplicación y puede crear falsos positivos.

Configuración básica

Crea una clase que extienda Application, regístrala en AndroidManifest.xml mediante el atributo android:name y agrega la configuración de StrictMode. ThreadPolicy.Builder incluye todos los detectores y todos los tipos de penalización (excepto dialog — solo funciona cuando hay un depurador conectado). VmPolicy.Builder agrega detectores para fugas de Activity y objetos Closable. Para proyectos grandes (100+ pantallas), se recomienda configurar VmPolicy con penaltyDeath en el detector de fugas de Activity — es estricto pero efectivo.

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            StrictMode.setVmPolicy(
                StrictMode.VmPolicy.Builder()
                    .detectActivityLeaks()
                    .detectLeakedClosableObjects()
                    .detectLeakedRegistrationObjects()
                    .penaltyLog()
                    .penaltyDeath()
                    .build()
            )
        }
    }
}

Integración en CI/CD

Para el control automático en CI/CD, usa penaltyDeath — si algún test viola la política, la aplicación fallará con una excepción. Combínalo con Android Test Orchestrator para que cada test se ejecute en un proceso limpio. Para tests de UI (Espresso, Compose Test), escribe un TestRule personalizado que intercepte las violaciones de StrictMode y las convierta en fallos de aserción. Ejemplo: en @Before, activa StrictMode, y en @After, comprueba que no hubo violaciones.

Configuración de umbrales

Por defecto, el umbral para customSlowCall es 2000 ms, para disk_read y disk_write — sin umbral (cualquier operación activa). Mediante setSlowCallDurationThreshold y setSlowIoDurationThreshold, puedes establecer tus propios valores en milisegundos. Si tu aplicación lee legítimamente SharedPreferences en el hilo principal (configuración pequeña), aumenta el umbral a 10–20 ms — esto filtrará las lecturas rápidas pero mantendrá las lentas.

Mejores prácticas de StrictMode

StrictMode es una herramienta potente pero delicada. Una configuración incorrecta genera millones de falsos positivos, lo que hace que los desarrolladores dejen de prestarles atención. A continuación, prácticas probadas recopiladas de la experiencia de grandes equipos de Android.

Activar solo en compilaciones de depuración

Esta es una regla estricta: StrictMode NUNCA debe estar activo en compilaciones de lanzamiento. Usa el flag BuildConfig.DEBUG o un buildConfigField personalizado. En compilaciones de lanzamiento, muchas bibliotecas de terceros realizan legítimamente operaciones en el hilo principal (inicialización de SDK, escritura de caché), y StrictMode creará falsos positivos. Además, penaltyDialog en una compilación de lanzamiento mostrará un diálogo al usuario final — lo cual es inaceptable.

Usar tres niveles de rigor

Para proyectos pequeños (1–10 pantallas), configura penaltyLog — los registros son suficientes para el análisis manual. Para proyectos medianos (10–50 pantallas), agrega penaltyDeath en network y customSlowCalls. Para proyectos grandes (50+ pantallas), activa el conjunto completo de políticas con penaltyDeath en CI/CD, y penaltyLog para el desarrollo local. Esta gradación evita sobrecargar a los desarrolladores con falsos crashes mientras controla estrictamente la calidad en el pipeline.

Manejo de falsos positivos

Algunas bibliotecas (Firebase, Crashlytics, Adjust) realizan legítimamente operaciones en segundo plano que StrictMode podría detectar incorrectamente. Soluciones: agrega la biblioteca a una lista blanca mediante penaltyListener, actualiza la biblioteca a una versión con cambio explícito a un hilo en segundo plano, o usa StrictMode.vmPolicy. En Android 11+, se introdujo StrictMode.OnVmViolationListener para el filtrado programático de violaciones por stack trace.

kotlin
// Filtrado de falsos positivos mediante penaltyListener
StrictMode.setThreadPolicy(
    StrictMode.ThreadPolicy.Builder()
        .detectAll()
        .penaltyListener { violation ->
            val stack = violation.stackTraceToString()
            if ("com.google.firebase" !in stack) {
                logViolation(violation)
            }
        }
        .build()
)

StrictMode vs Android Lint vs Perfiladores

StrictMode no es la única herramienta de control de calidad en el ecosistema Android. Para entender su lugar, comparémosla con Android Lint, Android Profiler y Perfetto según criterios clave: tiempo de comprobación, profundidad de análisis y automatización.

CriterioStrictModeAndroid LintProfiler / Perfetto
Tiempo de comprobaciónRuntime (mientras la aplicación se ejecuta)Compile time (antes del lanzamiento)Runtime (post-mortem)
Lo que compruebaDisco, red, fugasXML, código, recursosCPU, memoria, red, energía
AutomatizaciónCI/CD mediante penaltyDeathTarea de Gradle + lint-baselineRequiere análisis manual
ProfundidadSolo hilo de UI y fugasAnálisis estático de códigoPanorama completo de rendimiento
Falsos positivosMedios (dependen de las bibliotecas)Bajos (reglas configuradas)Ninguno (mediciones reales)

La mejor estrategia es combinar los tres enfoques: Android Lint detecta errores obvios en tiempo de compilación (por ejemplo, un IdleHandler olvidado), StrictMode detecta problemas en tiempo de ejecución, y Android Profiler / Perfetto se usa para análisis profundos cuando las dos primeras herramientas no dan respuestas. En proyectos reales (Google Maps, Instagram), StrictMode se introduce en la segunda semana de desarrollo — justo después de configurar la arquitectura básica.

Ejemplos de código con StrictMode

Veamos dos escenarios reales donde StrictMode ayuda a detectar y solucionar problemas de rendimiento: lectura de SharedPreferences en el hilo principal y fuga de Activity a través de un callback no registrado.

Detección de SharedPreferences lentos

Al iniciar la aplicación, StrictMode con la política detectDiskReads detectará la lectura de SharedPreferences en el hilo principal. Solución: cargar la configuración de forma asíncrona mediante CoroutineScope o almacenarla en caché en memoria al inicio. SharedPreferences lee sincrónicamente un archivo XML del disco — incluso con un archivo pequeño (1–2 KB), la operación toma de 1 a 5 ms, y hasta 20 ms en dispositivos baratos, lo que puede provocar la pérdida de fotogramas.

kotlin
// ❌ Código problemático — lectura de SharedPrefs en el hilo de UI
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // StrictMode detectDiskReads → ¡VIOLACIÓN!
        prefs = getSharedPreferences("config", MODE_PRIVATE)
    }
}

// ✅ Código corregido — lectura mediante Coroutine
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        loadConfigAsync()
    }
}

Detección de fugas de Activity

StrictMode con VmPolicy.detectActivityLeaks detectará una Activity que ha salido de la pila (se llamó a finish) pero el objeto Activity permanece en memoria debido a una referencia estática o un callback no registrado. Escenario típico: registro de EventBus o LocationListener en onResume sin llamar a unregister en onPause. VmPolicy mostrará un stack trace indicando la línea donde se creó la referencia.

kotlin
// ❌ Fuga — callback no cancelado
private var locationCallback: LocationCallback? = null

override fun onResume() {
    super.onResume()
    locationCallback = LocationCallback(this::onLocationUpdated)
    locationManager.register(locationCallback) // StrictMode → ¡FUGA!
}

override fun onPause() {
    super.onPause()
    // Olvidaste: locationManager.unregister(locationCallback)
}

Preguntas frecuentes

¿StrictMode ralentiza la aplicación?

StrictMode añade una pequeña sobrecarga — cada llamada al sistema se comprueba contra las políticas. El impacto en el rendimiento es del 1–3% en compilaciones de depuración y está ausente en las de lanzamiento (donde StrictMode está desactivado). Al activar detectAll en dispositivos antiguos (Android 6–8), la sobrecarga puede alcanzar el 5%, por lo que se recomienda configurar solo las políticas necesarias.

¿Se puede usar StrictMode con Jetpack Compose?

Sí, StrictMode es totalmente compatible con Jetpack Compose. Las políticas de disco y red funcionan a nivel del framework, independientemente del framework de UI. Además, en Compose la criticidad de los bloqueos de UI es mayor — Compose redibuja los fotogramas a 120 FPS en dispositivos de alta frecuencia de actualización, por lo que 5 ms adicionales en la lectura de archivos se vuelven más notables.

¿Por qué StrictMode no se activa al leer SharedPreferences?

A partir de Android 8.1 (API 27), SharedPreferences puede usar caché en memoria — si el archivo ya se ha leído, una nueva lectura no activará StrictMode. Asegúrate de llamar a getSharedPreferences por primera vez (lectura en frío) y de que la política detectDiskReads esté activa. También verifica que StrictMode no haya sido anulado en un fragmento sin padre.

¿Cómo desactivar StrictMode para tests individuales?

En tests JUnit, usa StrictMode.allowThreadDiskReads() y StrictMode.allowThreadDiskWrites() en @Before, y restaura la configuración en @After mediante StrictMode.enableDefaults(). Para tests de Instrumentación, usa un TestRunner personalizado con preservación temporal de la política original. En tests de Espresso, es conveniente envolver el código sensible a StrictMode en un IdlingResource.

¿Es necesario StrictMode en Kotlin Multiplatform?

StrictMode solo funciona en la plataforma Android a través del SDK de Android. En Kotlin Multiplatform (KMP), el código commonMain no puede usar StrictMode, pero para androidMain puedes agregarlo como de costumbre. Para la parte de iOS, usa un análogo — la aserción de DispatchQueue.main.async para el hilo principal.

Resumen

  • StrictMode — un detector en tiempo de ejecución de problemas de rendimiento en el hilo principal de Android
  • Las políticas se dividen en ThreadPolicy (disco, red) y VmPolicy (fugas de memoria)
  • La configuración toma 10 líneas de código en Application.onCreate con una comprobación de BuildConfig.DEBUG
  • Para CI/CD, usa penaltyDeath — una violación de política causa un crash de la aplicación
  • StrictMode no reemplaza sino que complementa a Android Lint y Perfetto
  • El filtrado adecuado de falsos positivos es la clave para un uso efectivo de la herramienta
  • Se recomienda introducir StrictMode en la segunda semana de desarrollo del proyecto

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.

Discutir el proyecto

Lea también