Inactive — un estado transitorio en el ciclo de vida de la aplicación entre Active y Background, en el que la app es visible en pantalla pero no recibe eventos táctiles. Explicamos cómo surge Inactive en iOS y Android, qué métodos del delegado lo manejan y cómo procesar correctamente las interrupciones — llamadas, notificaciones y gestos del sistema.
Puntos clave
Inactive es un estado intermedio en el ciclo de vida de la aplicación móvil que ocurre durante la transición entre Active y Background. En este estado, la app sigue en primer plano y es visible para el usuario, pero no recibe eventos táctiles, pulsaciones de teclas ni otros eventos de UI. El sistema bloquea la entrega de eventos a la app, pero la UI permanece en pantalla y no se minimiza.
La naturaleza de Inactive es temporal. Este estado dura exactamente lo que dura la interrupción del sistema: desde 0.1 segundos al cerrar rápidamente el Control Center hasta varios segundos durante una llamada entrante con pantalla de llamada. Una vez que termina la interrupción, la app vuelve a Active o pasa a Background si el usuario cambió a otra app. Inactive es el único estado que puede transitar en ambas direcciones: de vuelta a Active o hacia Background.
En iOS, Inactive es gestionado automáticamente por el sistema. El desarrollador no puede extender ni acortar el tiempo en Inactive — está completamente controlado por UIApplication. Lo único que puede hacer el desarrollador es manejar correctamente la transición a Inactive mediante applicationWillResignActive y el retorno mediante applicationDidBecomeActive. En Android, el equivalente es onPause, aunque la semántica difiere: onPause se llama incluso cuando una Activity está parcialmente cubierta por otro componente.
En iOS, Inactive es un estado separado del ciclo de vida de la aplicación (uno de cinco: Not Running, Active, Inactive, Background, Suspended). En Android no hay un equivalente directo — onPause señala que la Activity está perdiendo el foco de entrada pero puede permanecer visible (por ejemplo, al abrir un diálogo). La diferencia clave: Inactive en iOS es un estado de toda la app, mientras que onPause en Android es un estado por Activity. En multi-ventana de Android, una Activity puede estar en onPause (sin foco) mientras otra está en onResume (con foco).
| Característica | iOS Inactive | Android onPause |
|---|---|---|
| UI visible | Sí | Sí (parcial o totalmente) |
| Eventos táctiles | No recibe | No recibe |
| Duración | Hasta que termine la interrupción | Hasta que vuelva el foco o pase a fondo |
| Siguiente estado | Active o Background | onResume o onStop |
| Nivel | Aplicación (UIApplication) | Activity |
| Multi-ventana | Una escena activa | Múltiples Activity en onPause |
Inactive en iOS surge en varios escenarios estrictamente definidos. El usuario abre el Control Center (deslizar hacia abajo desde la esquina superior derecha en iPhone X+ o deslizar hacia arriba en modelos antiguos). El usuario abre el Notification Center (deslizar hacia abajo desde la esquina superior izquierda). Llega una llamada entrante — el sistema muestra la pantalla de llamada sobre la app. Se solicita un permiso del sistema — geolocalización, micrófono, cámara, contactos. En iPad, se inicia Slide Over o Split View — la escena activa se vuelve Inactive.
En Android, onPause (el equivalente de Inactive) surge en un rango aún más amplio de situaciones. Apertura de un diálogo (AlertDialog, DialogFragment). Superposición parcial de una Activity por otra Activity (por ejemplo, una Activity transparente para autenticación). Rotación de pantalla (la Activity se recrea, secuencia: onPause → onStop → onDestroy → onCreate → onStart → onResume). Modo multi-ventana — la ventana inactiva recibe onPause. Cada uno de estos eventos requiere suspender operaciones intensivas en recursos para preservar la batería y el rendimiento.
import UIKit
extension Notification.Name {
static let systemInterruptionBegan = Notification.Name("systemInterruptionBegan")
static let systemInterruptionEnded = Notification.Name("systemInterruptionEnded")
}
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationWillResignActive(_ application: UIApplication) {
// La aplicación pasa a Inactive — interrupción del sistema
print("Interrupción: Control Center, llamada o alerta del sistema")
// Pausar operaciones sensibles al tiempo
pauseVideoPlayback()
stopContinuousDataCollection()
hideSensitiveInformation()
// Notificar a los componentes
NotificationCenter.default.post(name: .systemInterruptionBegan, object: nil)
}
// Regreso de Inactive a Active
func applicationDidBecomeActive(_ application: UIApplication) {
resumeVideoPlayback()
restartDataCollection()
NotificationCenter.default.post(name: .systemInterruptionEnded, object: nil)
}
private func pauseVideoPlayback() {
// Pausar el vídeo para que el audio no se superponga
}
private func hideSensitiveInformation() {
// Ocultar datos sensibles al capturar pantalla
// Control Center/App Switcher toman una captura de la UI
}
}El código muestra el manejo de Inactive en UIKit. applicationWillResignActive pausa el vídeo, detiene la recopilación de datos y oculta información sensible. Esto es importante porque al abrir el Control Center o App Switcher, el sistema toma una captura de la UI actual — el usuario podría ver datos confidenciales en la vista previa. NotificationCenter permite que los componentes de la app se suscriban a eventos de interrupción.
En iOS, Inactive se maneja con un par de métodos: applicationWillResignActive (transición a Inactive) y applicationDidBecomeActive (retorno de Inactive). Estos métodos son parte de UIApplicationDelegate y se llaman en cada transición a través de Inactive. Desde iOS 13 y UISceneDelegate, se han añadido sceneWillResignActive y sceneDidBecomeActive para escenarios multi-ventana.
En iPad con iOS 13+, una app puede tener múltiples escenas (ventanas). Cada escena tiene su propio ciclo de vida. Una escena puede volverse Inactive (el usuario cambió a otra escena) mientras otra permanece Active. Esta es una diferencia importante respecto al iPhone, donde Inactive es un estado global para toda la app. Al desarrollar para iPad, es necesario manejar Inactive para cada escena por separado.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
// La escena se vuelve inactiva
func sceneWillResignActive(_ scene: UIScene) {
// En iPad esta escena pierde el foco, pero otras pueden estar activas
print("La escena pierde actividad")
// Pausar las tareas de esta escena
pauseSceneSpecificOperations()
}
// La escena se vuelve activa
func sceneDidBecomeActive(_ scene: UIScene) {
print("La escena se ha vuelto activa")
resumeSceneSpecificOperations()
}
private func pauseSceneSpecificOperations() {
// Pausar operaciones específicas de esta escena
}
private func resumeSceneSpecificOperations() {
// Reanudar operaciones al recuperar el foco
}
}
// AppDelegate sigue siendo el punto de entrada, delega a las escenas
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions
) -> UISceneConfiguration {
return UISceneConfiguration(
name: "Default Configuration",
sessionRole: connectingSceneSession.role
)
}
}El código muestra un SceneDelegate para manejar Inactive a nivel de escena. sceneWillResignActive se llama cuando una ventana específica pierde el foco — esto puede ocurrir al cambiar entre ventanas en iPad. AppDelegate configura UISceneConfiguration para soportar multi-ventana. Cada escena tiene un estado independiente y el desarrollador debe manejarlas por separado.
En Android, el equivalente directo de Inactive en iOS es el método onPause() del ciclo de vida de Activity. Se llama cuando la Activity pierde el foco de entrada pero puede permanecer visible. Escenarios típicos: apertura de un diálogo, lanzamiento de otra Activity en la misma app, llamada entrante, pulsación del botón Home o Recents. En onPause, el desarrollador debe suspender operaciones intensivas en recursos — animaciones, reproducción de vídeo, trabajo con la cámara.
Una diferencia importante de Android es que onPause siempre precede a onStop, pero no al revés. Una Activity puede recibir onPause sin onStop (por ejemplo, al abrir una Activity transparente). Además, onPause puede llamarse múltiples veces durante la vida de una Activity — en cada cambio de foco. No coloques lógica de una sola vez en onPause — usa onStop para operaciones finales y onPause solo para suspender acciones interactivas.
class VideoPlayerActivity : AppCompatActivity() {
private var exoPlayer: ExoPlayer? = null
private var currentPosition: Long = 0L
override fun onPause() {
super.onPause()
// La aplicación pierde el foco — pausamos el vídeo
exoPlayer?.let { player ->
if (player.isPlaying) {
currentPosition = player.currentPosition
player.pause()
}
}
// Ocultamos datos sensibles (GDPR/pantallas bancarias)
if (window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_SECURE == 0
) {
hideSensitiveOverlay()
}
}
override fun onResume() {
super.onResume()
// Vuelve el foco — reanudamos la reproducción
exoPlayer?.seekTo(currentPosition)
exoPlayer?.play()
showSensitiveOverlay()
}
private fun hideSensitiveOverlay() {
// Superponemos una pantalla negra sobre los datos financieros
}
}El código muestra el manejo correcto de onPause para un reproductor de vídeo. ExoPlayer se pausa cuando se pierde el foco, y se guarda la posición de reproducción. Al volver a onResume, el reproductor reanuda la reproducción desde la posición guardada. Además, se muestra un patrón para ocultar datos sensibles — importante para aplicaciones financieras y médicas que requieren protección contra capturas de pantalla al cambiar de app.
Primera regla — oculta los datos confidenciales al transicionar a Inactive. Cuando el usuario abre el Control Center o App Switcher, iOS toma una captura de la pantalla actual. En Android, de manera similar, el sistema muestra una vista previa de la última Activity en Recents. Usa UIApplication.shouldSnapshotSecureApp (iOS 16+) o FLAG_SECURE (Android) para proteger pantallas confidenciales.
Segunda regla — pausa animaciones y contenido multimedia. Inactive no es un buen momento para reproducir vídeo o animaciones, ya que el usuario no puede verlas. Además, la reproducción en segundo plano puede superponer el audio con los sonidos del sistema (tono de llamada, notificación). Detén AVPlayer, ExoPlayer y UIView.animate al ir a Inactive y reanúdalos al volver a Active.
Tercera regla — bloquea la entrada de datos. Si la app contiene formularios o borradores, bloquea el teclado y los campos de entrada al ir a Inactive. Esto evita la entrada accidental al regresar y protege contra la interceptación de datos a través de superposiciones del sistema. En iOS, renuncia al primer respondedor (view.endEditing(true)), en Android — limpia el foco (currentFocus?.clearFocus()).
Cuarta regla — no realices operaciones largas en applicationWillResignActive o onPause. Estos métodos deben completarse en fracciones de segundo. Si necesitas guardar una gran cantidad de datos, comienza a guardar en un hilo en segundo plano y complétalo en applicationDidEnterBackground o onStop. iOS da 5 segundos para ejecutar applicationWillResignActive, después de lo cual el sistema puede terminar la app forzosamente.
import UIKit
final class SecureOverlayManager {
private var blurView: UIVisualEffectView?
func showBlurOverlay() {
guard let window = UIApplication.shared.keyWindow,
blurView == nil
else { return }
let blur = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
blur.frame = window.bounds
blur.autoresizingMask = [.flexibleWidth, .flexibleHeight]
window.addSubview(blur)
blurView = blur
}
func removeBlurOverlay() {
blurView?.removeFromSuperview()
blurView = nil
}
}
// Uso en AppDelegate
func applicationWillResignActive(_ application: UIApplication) {
SecureOverlayManager().showBlurOverlay()
}
func applicationDidBecomeActive(_ application: UIApplication) {
SecureOverlayManager().removeBlurOverlay()
}El código muestra la implementación de una superposición segura para proteger datos durante la transición a Inactive. Un UIVisualEffectView con efecto blur se superpone sobre toda la UI al ir a Inactive y se elimina al volver a Active. Esto garantiza que los datos confidenciales no sean visibles en las capturas de App Switcher y Control Center. De manera similar, puedes usar UIImageView con un logotipo para una superposición con la marca.
Preguntas frecuentes
Sí. Inactive es un estado intermedio obligatorio antes de pasar a Background en iOS. Una app no puede ir de Active directamente a Background — primero se vuelve Inactive, luego Background. En Android, de manera similar, onPause siempre se llama antes de onStop. Esto le da al desarrollador la oportunidad de preparar los datos para guardarlos antes de ir completamente al fondo.
Sí. En iPad, al iniciar Slide Over o Split View, la escena activa se vuelve Inactive, aunque no ocurra ninguna interrupción del sistema — el usuario simplemente está interactuando con otra escena. Esta es una característica de iPadOS multi-ventana. En iPhone, Inactive siempre es provocado por una interrupción del sistema — llamada, notificación, Control Center o Notification Center.
Generalmente de 0.1 a 2 segundos. Durante una llamada entrante con pantalla de llamada — hasta 30 segundos (hasta que el usuario responda o rechace la llamada). iOS no limita forzosamente el tiempo en Inactive, pero el sistema puede terminar la app si no responde a los eventos (watchdog). En Android, onPause no tiene límite de tiempo, pero se recomienda completar el trabajo en 200 ms.
ScenePhase.inactive — el valor del enum ScenePhase que se establece cuando la escena está en primer plano pero no recibe eventos. En SwiftUI, puedes observarlo a través de @Environment(\.scenePhase) y reaccionar mediante onChange. Al transicionar de .active a .inactive, pausa temporizadores y animaciones. Al volver a .active, reanúdalos. Al ir a .background, guarda el estado.
No, solo para apps que manejan datos confidenciales: bancarias, médicas, corporativas y mensajería con chats privados. Para juegos y apps de entretenimiento, no es necesario ocultar la UI. Sin embargo, pausar el juego y el sonido durante Inactive es una buena práctica para evitar la superposición de audio con notificaciones del sistema. Apple recomienda ocultar datos sensibles pero no lo exige.
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