Notification Service Extension es una extensión de iOS que intercepta una notificación push antes de que se muestre al usuario y permite modificar el contenido. La extensión puede descifrar datos encriptados, descargar archivos multimedia, cambiar el texto o agregar campos personalizados. Según Apple Developer, 2025, Notification Service Extension tiene hasta 30 segundos para completar la tarea en segundo plano.
Puntos clave
Notification Service Extension es una extensión de aplicación en iOS que se ejecuta antes de mostrar una notificación push. Permite que el servidor envíe un payload mínimo mientras la extensión lo enriquece con contenido: descargar imágenes, descifrar datos, reemplazar texto. El usuario ve la notificación ya procesada.
Cuando iOS recibe una notificación push, el sistema verifica si existe una extensión para la aplicación. Si la extensión está registrada, iOS la inicia en un proceso en segundo plano y pasa el contenido de la notificación a través del método didReceive(_:withContentHandler:). La extensión procesa el contenido y llama a contentHandler con el contenido modificado. Si la extensión no completa el proceso en 30 segundos, el sistema muestra la notificación original.
Service Extension es necesario en escenarios donde el contenido de la notificación requiere procesamiento en el dispositivo. Comunicaciones seguras: el servidor envía un payload encriptado, la extensión lo descifra localmente. Notificaciones multimedia enriquecidas: el servidor envía la URL de una imagen, la extensión la descarga y la adjunta. Localización dinámica: la extensión sustituye el texto en el idioma del dispositivo.
| Escenario | Sin extensión | Con extensión |
|---|---|---|
| Imagen | No compatible | Se descarga y se muestra |
| Encriptación | El servidor guarda la clave | Descifrado en el dispositivo |
| Texto | Fijo en el servidor | Sustitución dinámica |
| Validación | No se verifica | Notificaciones maliciosas canceladas |
Notification Service Extension funciona en un entorno limitado. El tiempo máximo de ejecución es de 30 segundos. La extensión no tiene acceso al almacenamiento principal de la aplicación (excepto App Group). El tamaño de la extensión está limitado a 50 MB. Cuando se supera el tiempo, el sistema llama a contentHandler con el contenido original y todos los cambios se pierden.
En Xcode, Notification Service Extension se agrega creando un nuevo target del tipo Notification Service Extension. Xcode genera una clase de plantilla NotificationService que hereda de UNNotificationServiceExtension, con dos métodos: didReceive y serviceExtensionTimeWillExpire.
En Xcode, seleccione File → New → Target → Notification Service Extension. Ingrese un nombre (por ejemplo, PushNotificationService) y elija el lenguaje Swift. Asegúrese de que el target se agregue a la aplicación principal y tenga la firma correcta. Después de la creación, se generará la clase NotificationService.swift con una implementación básica.
El Info.plist de la extensión contiene la clave NSExtension con las subclaves NSExtensionPointIdentifier (com.apple.usernotifications.service) y NSExtensionPrincipalClass (el nombre de su controlador). Adicionalmente, se pueden especificar NSExtensionAttributes con reglas de activación de la extensión. Xcode genera estas configuraciones automáticamente.
La implementación básica sobrescribe didReceive, modifica el contenido de la notificación y llama a contentHandler. Si el procesamiento lleva demasiado tiempo, se llama a serviceExtensionTimeWillExpire, donde debe completar el trabajo con el estado actual.
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(
request: UNNotificationRequest,
withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
contentHandler = handler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
bestAttemptContent.title = "[Procesado] \(bestAttemptContent.title)"
contentHandler?(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
Uno de los usos clave de Service Extension es descifrar el contenido de la notificación en el dispositivo. El servidor envía un payload encriptado y la extensión lo descifra utilizando una clave almacenada en Keychain o App Group. Esto garantiza que el contenido no pueda ser interceptado durante la transmisión.
El servidor encripta el cuerpo de la notificación utilizando una clave simétrica (AES-256). La clave de encriptación se acuerda previamente entre el cliente y el servidor. La extensión recibe la cadena encriptada en el campo data del payload, la descifra y la sustituye en los campos de la notificación. La clave del usuario puede obtenerse de Keychain después de la autenticación.
override func didReceive(
request: UNNotificationRequest,
withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
guard let content = request.content.mutableCopy()
as? UNMutableNotificationContent else {
handler(request.content)
return
}
guard let encryptedData = content.userInfo["encrypted_data"]
as? String else {
handler(content)
return
}
let decrypted = CryptoService.decrypt(encryptedData)
content.body = decrypted.body
content.title = decrypted.title
handler(content)
}
La clave de descifrado no debe almacenarse en el código de la extensión ni en NSUserDefaults. Utilice iOS Keychain con acceso a través de App Group para que tanto la aplicación como la extensión puedan leer la clave. Utilice Security.framework con el algoritmo AES-256-GCM para la generación de claves en el cliente.
El uso más común de Notification Service Extension es descargar imágenes, GIF y videos para mostrarlos en la notificación. El servidor envía la URL de un archivo multimedia y la extensión lo descarga, lo guarda en un directorio temporal y crea un UNNotificationAttachment.
La extensión recibe la URL de la imagen del campo payload de la notificación. Usando URLSession, la extensión descarga el archivo a un directorio temporal. Una vez completada la descarga, se crea un UNNotificationAttachment con la URL local. El adjunto se pasa al contenido modificado. iOS automáticamente muestra la imagen en la interfaz estándar o en una Notification Content Extension.
private func downloadAndAttachMedia(
content: UNMutableNotificationContent,
mediaUrl: String,
handler: @escaping (UNNotificationContent) -> Void
) {
guard let url = URL(string: mediaUrl) else {
handler(content)
return
}
let task = URLSession.shared.downloadTask(with: url) { localUrl, _, error in
guard let localUrl = localUrl, error == nil else {
handler(content)
return
}
let attachment = try? UNNotificationAttachment(
identifier: "media",
url: localUrl,
options: nil
)
if let attachment = attachment {
content.attachments = [attachment]
}
handler(content)
}
task.resume()
}
iOS admite los siguientes formatos para mostrar en notificaciones: JPEG, PNG, GIF (estáticos), video MPEG-4 de hasta 50 MB. Para archivos de audio, se admiten MP3, AAC y ALAC. Importante: todos los archivos multimedia deben descargarse dentro del límite de 30 segundos. Para archivos grandes, se recomienda el recorte en el servidor o la carga progresiva.
Gestionar el límite de 30 segundos es una tarea clave al desarrollar Notification Service Extension. Si la extensión no completa el procesamiento a tiempo, el sistema llama a serviceExtensionTimeWillExpire y muestra el contenido original. Se deben prever escenarios de fallback para cada tipo de procesamiento.
Divida las tareas por prioridad. Realice primero las modificaciones críticas (descifrado, localización básica). Las mejoras opcionales (descarga de imágenes, enriquecimiento de texto) van después. Utilice URLSession con tiempos de espera para las solicitudes de red, evitando gastar todo el límite en una sola operación.
Si la descarga de la imagen falla o el descifrado del payload devuelve un error, la extensión debe llamar a contentHandler con el contenido original. Nunca termine la extensión sin llamar a contentHandler, ya que esto provoca la pérdida de la notificación. Un fallback seguro siempre debe estar previsto en el código de la extensión.
override func didReceive(
request: UNNotificationRequest,
withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
let content = (request.content.mutableCopy()
as? UNMutableNotificationContent) ?? request.content
// Tarea crítica: descifrado
var decryptedContent = tryDecryptPayload(content)
// Tarea opcional: medios
guard let mediaUrl = decryptedContent.userInfo["media_url"]
as? String else {
handler(decryptedContent)
return
}
downloadAndAttachMedia(
content: decryptedContent,
mediaUrl: mediaUrl,
handler: handler
)
}
Para probar Notification Service Extension, use Xcode: seleccione el target de la extensión, ejecútelo en el simulador y envíe una notificación push a través de la terminal o Firebase Console. Registre cada etapa del procesamiento usando os_log, esto ayuda a diagnosticar problemas de tiempo y descarga.
Preguntas frecuentes
El sistema llama a serviceExtensionTimeWillExpire, luego muestra la notificación original sin cambios. Todos los archivos descargados y las modificaciones se descartan.
Sí, si llama a contentHandler con contenido vacío (UNNotificationContent con campos vacíos), la notificación no se mostrará. Esto se utiliza para filtrar notificaciones spam o datos incorrectos.
El token se puede pasar en el userInfo del payload de la notificación u obtenerlo de Keychain a través de App Group. No se recomienda almacenar tokens en UserDefaults de la extensión.
La extensión debe estar firmada con el mismo certificado de desarrollador que la aplicación principal. Para producción, se requiere un certificado de producción con la capacidad Push Notifications habilitada.
Conecte el dispositivo a Xcode, seleccione el target de la extensión en el esquema de ejecución y envíe una notificación push a través de Firebase Console. Los breakpoints en la extensión funcionan igual que en la aplicación principal.
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