Background es un estado del ciclo de vida de la aplicación en el que continúa ejecutándose pero no se muestra en pantalla. Explicamos los fundamentos del trabajo en segundo plano en iOS y Android: limitaciones, tiempos de espera, tareas en segundo plano mediante beginBackgroundTask, WorkManager y Service, así como las mejores prácticas para un manejo correcto de Background.
Puntos Clave
Background es un estado de la aplicación en el que continúa existiendo en el sistema operativo, ejecuta código y consume recursos, pero no se muestra en la pantalla del dispositivo. El usuario está en la pantalla de inicio, en otra aplicación o la pantalla del dispositivo está bloqueada. En iOS, Background sigue a Inactive — la cadena de transición es: Active → Inactive → Background. En Android, onStop señala la transición de una Activity a Background.
Ambas plataformas imponen restricciones estrictas al trabajo en segundo plano. iOS proporciona una ventana limitada (generalmente 30 segundos) para ejecutar código después de entrar en Background, después de lo cual la aplicación pasa a Suspended. Android es más flexible: un Foreground Service con una notificación visible puede ejecutarse indefinidamente, pero un Background Service normal está limitado a unos minutos. La tarea clave del desarrollador es guardar correctamente el estado y programar la continuación del trabajo a través de las API del sistema para tareas en segundo plano.
El sistema puede terminar una aplicación en segundo plano en cualquier momento cuando hay poca memoria. Al terminar, todos los datos no guardados se pierden. Por lo tanto, es críticamente importante guardar el estado en applicationDidEnterBackground (iOS) o onStop (Android). Después de la terminación, el próximo inicio comienza desde Not Running con un inicio en frío y restaura el estado guardado.
Es importante distinguir Background de Suspended. Background — la aplicación está ejecutando código activamente. Suspended — la aplicación está en memoria pero no ejecuta código — está congelada. En iOS, la aplicación pasa de Background a Suspended después de completar las tareas en segundo plano. Android no tiene Suspended — el proceso existe (incluyendo Background) o está terminado (Not Running). Sin embargo, Android puede pausar la ejecución de hilos mediante LMK (Low Memory Killer).
| Característica | iOS Background | Android Background |
|---|---|---|
| Ejecuta código | Sí, hasta 30 segundos | Sí, depende de la API |
| UI visible | No | No |
| Tiempo de espera predeterminado | ~30 seg (beginBackgroundTask) | Varios minutos (Service) |
| Trabajo ilimitado | Solo categorías especiales (audio, VoIP, navegación) | Foreground Service con notificación |
| Garantía de ejecución | No — el sistema puede terminar en cualquier momento | WorkManager garantiza la ejecución |
| Permiso requerido | Sí — capabilities en Info.plist | Sí — permiso FOREGROUND_SERVICE |
| Siguiente estado | Suspended → Not Running | Not Running (o reinicio) |
En iOS, Background se maneja a través del método delegado applicationDidEnterBackground. En este método, el desarrollador debe guardar el estado del usuario, liberar recursos y completar las tareas en segundo plano. Para ejecutar código después de entrar en Background, se utiliza beginBackgroundTask(expirationHandler:) — una API que solicita tiempo adicional al sistema (generalmente 30 segundos). Si la tarea no se completa dentro de este tiempo, se llama a expirationHandler y la aplicación pasa forzosamente a Suspended.
Con iOS 13, Apple presentó BGTaskScheduler — una API moderna para programar tareas en segundo plano. A diferencia de beginBackgroundTask, que solo da tiempo para finalizar después de ir al fondo, BGTaskScheduler permite programar la ejecución de tareas en el futuro — por ejemplo, actualizar contenido una vez por hora o subir análisis por la noche. BGTaskScheduler es el enfoque recomendado para nuevos proyectos, ya que es más eficiente en términos de batería.
import UIKit
import BackgroundTasks
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
// La aplicación pasó al fondo — iniciando tarea en segundo plano
func applicationDidEnterBackground(_ application: UIApplication) {
saveAppState()
startBackgroundTask()
}
private func startBackgroundTask() {
backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
// Tiempo agotado — finalizando forzosamente
self?.endBackgroundTask()
}
// Simulando trabajo en segundo plano (guardando datos en el servidor)
DispatchQueue.global().async { [weak self] in
uploadAnalyticsData()
self?.endBackgroundTask()
}
}
private func endBackgroundTask() {
guard backgroundTaskID != .invalid else { return }
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
// Registro de BGTaskScheduler
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.example.refresh",
using: nil
) { task in
handleAppRefresh(task: task as! BGAppRefreshTask)
}
return true
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.example.refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 3600)
try? BGTaskScheduler.shared.submit(request)
}
func handleAppRefresh(task: BGAppRefreshTask) {
scheduleAppRefresh()
task.expirationHandler = { task.setTaskCompleted(success: false) }
fetchLatestData { result in
task.setTaskCompleted(success: result)
}
}
}El código muestra el manejo completo de Background en iOS. applicationDidEnterBackground inicia una tarea en segundo plano mediante beginBackgroundTask con un tiempo de espera y expirationHandler. Paralelamente, se registra BGTaskScheduler para actualizaciones periódicas de contenido. beginBackgroundTask se usa para tareas de finalización inmediata, BGTaskScheduler para planificación a largo plazo. Ambas API requieren una gestión adecuada de los identificadores de tareas.
En Android, Background se gestiona a través de varias API. El Service tradicional permite ejecutar código en segundo plano, pero desde Android 8+ (API 26), el Background Service está limitado: el sistema lo termina unos minutos después de que la aplicación pasa al fondo. Un Foreground Service con una notificación persistente puede ejecutarse indefinidamente. WorkManager es la solución recomendada para tareas en segundo plano con garantía de ejecución incluso después de reiniciar el dispositivo.
Android, a diferencia de iOS, admite procesos en segundo plano de larga duración. Foreground Service se usa para tareas que el usuario debe ver — reproducción de música, navegación, registro de entrenamientos. JobScheduler y WorkManager se usan para tareas que pueden diferirse: sincronización de datos, subida de registros, actualización de caché. La diferencia clave: Android permite programar tareas con condiciones — Wi-Fi, carga, inactividad del dispositivo — lo que ahorra batería y tráfico.
import android.app.Service
import android.content.Intent
import android.os.IBinder
import androidx.work.*
// 1. Foreground Service para trabajo prolongado en segundo plano
class SyncService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = createNotification()
startForeground(NOTIFICATION_ID, notification)
performBackgroundWork()
return START_STICKY
}
private fun performBackgroundWork() {
Thread {
// Sincronización de datos con el servidor
syncDataToServer()
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
}.start()
}
override fun onBind(intent: Intent?): IBinder? = null
}
// 2. WorkManager para tareas diferidas en segundo plano
class DataSyncWorker(
private val context: Context,
private val params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
// Subida de análisis al servidor
uploadAnalytics()
Result.success()
} catch (e: Exception) {
if (runAttemptCount < 3) Result.retry() else Result.failure()
}
}
}
// Programación de tarea WorkManager
fun scheduleBackgroundSync(context: Context) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
val request = OneTimeWorkRequestBuilder<DataSyncWorker>()
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
.build()
WorkManager.getInstance(context).enqueue(request)
}El código muestra dos enfoques para el trabajo en segundo plano en Android. SyncService — un Foreground Service con notificación para trabajo inmediato y prolongado en segundo plano. DataSyncWorker — WorkManager para tareas diferidas con condiciones (Wi-Fi, carga). WorkManager garantiza la ejecución incluso después de reiniciar el dispositivo y admite backoff exponencial para reintentos. Foreground Service requiere una notificación persistente en la barra de estado.
Ambas plataformas móviles están endureciendo constantemente las reglas del trabajo en segundo plano. En iOS, cada nueva generación del SO reduce el tiempo de ejecución en segundo plano y añade nuevas restricciones. En Android, Google introduce modos de ahorro de energía cada vez más estrictos (Doze, App Standby). Los desarrolladores deben mantenerse al día con las limitaciones actuales para evitar que la aplicación sea terminada prematuramente por el sistema.
En iOS, a partir de iOS 13, el sistema desactiva las tareas en segundo plano para las aplicaciones que abusan del tiempo en segundo plano. Cada aplicación recibe ciertos límites basados en el comportamiento del usuario. BGTaskScheduler programa la ejecución en momentos óptimos — por ejemplo, cuando el dispositivo está conectado a Wi-Fi y cargándose. Las aplicaciones que usan correctamente BGTaskScheduler obtienen más tiempo en segundo plano.
En Android, a partir de Android 9 (API 28), el trabajo en segundo plano está restringido por el modo Doze, que se activa cuando el dispositivo está inactivo. Las aplicaciones en Doze no pueden realizar tareas en segundo plano, la red se desconecta, JobScheduler y WorkManager difieren las tareas hasta salir de Doze. Foreground Service es la única forma de evitar Doze, pero el abuso lleva a que la aplicación sea bloqueada por el usuario y se revoquen los permisos.
| Restricción | iOS | Android |
|---|---|---|
| Tiempo de espera de tarea en segundo plano | ~30 segundos (beginBackgroundTask) | Varios minutos (JobScheduler) |
| Segundo plano ilimitado | Audio, VoIP, navegación, Bluetooth | Foreground Service + notificación |
| Ahorro de energía | Low Power Mode — desactiva tareas en segundo plano | Doze, App Standby, Battery Optimization |
| Programación | BGTaskScheduler (iOS 13+) | WorkManager (Android Jetpack) |
| Después de reinicio | Solo notificación push | WorkManager conserva las tareas |
| Tiempo máximo de ejecución | ~30 minutos (audio) | Ilimitado (Foreground Service) |
Primera regla — minimice el consumo de recursos en segundo plano. La mayoría de las tareas en segundo plano pueden diferirse para cuando el dispositivo se esté cargando y esté conectado a Wi-Fi. Use BGTaskScheduler (iOS) y WorkManager (Android) para programar tareas con condiciones. No ejecute cálculos pesados en segundo plano — esto agota la batería y provoca limitación de la CPU.
Segunda regla — especifique siempre un expirationHandler para beginBackgroundTask. Si la aplicación no completa la tarea en el tiempo asignado, el sistema la pasará forzosamente a Suspended o la terminará. El expirationHandler es la última oportunidad para guardar datos y finalizar el trabajo correctamente. En Android, use setForegroundAsync en WorkManager para convertir una tarea normal en primer plano si se necesita más tiempo.
Tercera regla — verifique las restricciones de trabajo en segundo plano antes de iniciar. En iOS, use UIApplication.shared.backgroundTimeRemaining para comprobar el tiempo restante. En Android, verifique ActivityManager.isBackgroundRestricted() — si es true, la aplicación no puede ejecutar tareas en segundo plano, y debe sugerir al usuario que elimine las restricciones en la configuración. Esto es especialmente importante para aplicaciones con funciones críticas en segundo plano — alarmas, calendarios, sincronización.
Cuarta regla — pruebe las tareas en segundo plano en un dispositivo real. Los simuladores y emuladores no reproducen las restricciones reales del trabajo en segundo plano. En iOS, use Debug → Simulate Background Fetch en Xcode. En Android, use adb shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED para probar WorkManager después del reinicio. Las pruebas reales en un dispositivo con batería baja revelan la mayoría de los problemas del trabajo en segundo plano.
import UIKit
final class BackgroundTaskManager {
static let shared = BackgroundTaskManager()
private var tasks: [String: UIBackgroundTaskIdentifier] = [:]
func startTask(name: String, expiration: @escaping () -> Void) {
let remaining = UIApplication.shared.backgroundTimeRemaining
print("Tiempo restante en segundo plano: \(remaining) seg")
let task = UIApplication.shared.beginBackgroundTask { [weak self] in
print("Tiempo agotado para la tarea: \(name)")
expiration()
self?.endTask(name: name)
}
tasks[name] = task
}
func endTask(name: String) {
guard let task = tasks.removeValue(forKey: name),
task != .invalid
else { return }
UIApplication.shared.endBackgroundTask(task)
}
}El código muestra un administrador de tareas en segundo plano que rastrea el tiempo restante y gestiona los identificadores. backgroundTimeRemaining devuelve el número de segundos antes de la terminación forzada — si el valor es infinito, la aplicación se ejecuta sin restricciones (audio, navegación). El administrador permite lanzar múltiples tareas en segundo plano con diferentes nombres y completar cada una correctamente. Este enfoque previene fugas de tareas en segundo plano y garantiza que el sistema no termine la aplicación debido a tareas no cerradas.
Preguntas Frecuentes
Sí, para un número limitado de categorías: audio (AVAudioSession categoría .playback), VoIP (PushKit), navegación (CLLocationManager con allowsBackgroundLocationUpdates), Bluetooth (central background mode), actualización en segundo plano (BGTaskScheduler). Para todas las demás — un máximo de 30 segundos. En iOS 16+, Apple ha endurecido los requisitos incluso para las categorías permitidas.
beginBackgroundTask es una API síncrona para extender la vida de la aplicación ~30 segundos después de ir al fondo. Se llama en applicationDidEnterBackground. BGTaskScheduler es una API asíncrona para programar tareas en el futuro mediante disparadores del sistema (tiempo, ubicación, actualización de contenido). BGTaskScheduler es el enfoque moderno, recomendado por Apple para iOS 13+.
A partir de Android 8 (API 26), un Background Service se termina unos minutos después de que la aplicación pasa al fondo. Solución: use un Foreground Service con notificación para operaciones largas o WorkManager para tareas diferidas. Verifique la Optimización de Batería para su aplicación en la configuración — si está optimizada, el sistema puede diferir o cancelar las tareas en segundo plano.
Presione Cmd+Shift+H para ir a la pantalla de inicio. En Xcode, use Debug → Simulate Background Fetch. Para verificar beginBackgroundTask, abra la consola (Shift+Cmd+C) y llame a e UIApplication.shared.backgroundTimeRemaining. En Xcode 15+, hay un escenario de Background Execution disponible en la pestaña Diagnostics del simulador.
Process Death es la terminación de un proceso de Android por el sistema cuando hay pocos recursos o cuando está inactivo en segundo plano. A diferencia de iOS, Android no tiene Suspended — el proceso está vivo (puede estar en segundo plano) o muerto (Not Running). Process Death es un comportamiento normal del SO, y la aplicación debe restaurar correctamente el estado después mediante SavedStateHandle, onSaveInstanceState o DataStore.
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