Notification Service Extension est une extension iOS qui intercepte une notification push avant son affichage à l'utilisateur et permet de modifier le contenu. L'extension peut déchiffrer des données cryptées, télécharger des pièces jointes multimédia, modifier le texte ou ajouter des champs personnalisés. Selon Apple Developer, 2025, Notification Service Extension dispose de jusqu'à 30 secondes pour accomplir la tâche en arrière-plan.
Points clés
Notification Service Extension est une extension d'application iOS qui s'exécute avant l'affichage d'une notification push. Elle permet au serveur d'envoyer un payload minimal tandis que l'extension l'enrichit avec du contenu : téléchargement d'images, déchiffrement de données, remplacement de texte. L'utilisateur voit la notification déjà traitée.
Lorsque iOS reçoit une notification push, le système vérifie si une extension existe pour l'application. Si l'extension est enregistrée, iOS la lance dans un processus d'arrière-plan et transmet le contenu de la notification via la méthode didReceive(_:withContentHandler:). L'extension traite le contenu et appelle contentHandler avec le contenu modifié. Si l'extension ne termine pas dans les 30 secondes, le système affiche la notification d'origine.
Service Extension est nécessaire dans les scénarios où le contenu de la notification nécessite un traitement sur l'appareil. Communications sécurisées : le serveur envoie un payload crypté, l'extension le déchiffre localement. Notifications multimédia enrichies : le serveur envoie une URL d'image, l'extension la télécharge et la joint. Localisation dynamique : l'extension substitue le texte dans la langue de l'appareil.
| Scénario | Sans extension | Avec extension |
|---|---|---|
| Image | Non supporté | Téléchargée et affichée |
| Cryptage | Le serveur stocke la clé | Déchiffrement sur l'appareil |
| Texte | Fixe sur le serveur | Substitution dynamique |
| Validation | Non vérifiée | Notifications malveillantes annulées |
Notification Service Extension fonctionne dans un environnement limité. Le temps d'exécution maximum est de 30 secondes. L'extension n'a pas accès au stockage principal de l'application (sauf App Group). La taille de l'extension est limitée à 50 Mo. Lorsque le temps est dépassé, le système appelle contentHandler avec le contenu d'origine et toutes les modifications sont perdues.
Dans Xcode, Notification Service Extension s'ajoute en créant une nouvelle cible de type Notification Service Extension. Xcode génère une classe modèle NotificationService héritant de UNNotificationServiceExtension, avec deux méthodes : didReceive et serviceExtensionTimeWillExpire.
Dans Xcode, sélectionnez File → New → Target → Notification Service Extension. Entrez un nom (par exemple, PushNotificationService) et choisissez le langage Swift. Assurez-vous que la cible est ajoutée à l'application principale et possède la signature correcte. Après la création, la classe NotificationService.swift avec une implémentation de base sera générée.
Le fichier Info.plist de l'extension contient la clé NSExtension avec les sous-clés NSExtensionPointIdentifier (com.apple.usernotifications.service) et NSExtensionPrincipalClass (le nom de votre contrôleur). De plus, NSExtensionAttributes peuvent être spécifiés avec des règles d'activation de l'extension. Xcode génère ces paramètres automatiquement.
L'implémentation de base redéfinit didReceive, modifie le contenu de la notification et appelle contentHandler. Si le traitement prend trop de temps, serviceExtensionTimeWillExpire est appelé, où vous devez terminer le travail avec l'état actuel.
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 = "[Traité] \(bestAttemptContent.title)"
contentHandler?(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
L'une des utilisations clés de Service Extension est le déchiffrement du contenu de la notification sur l'appareil. Le serveur envoie un payload crypté et l'extension le déchiffre en utilisant une clé stockée dans Keychain ou App Group. Cela garantit que le contenu ne peut pas être intercepté pendant la transmission.
Le serveur crypte le corps de la notification en utilisant une clé symétrique (AES-256). La clé de cryptage est préalablement convenue entre le client et le serveur. L'extension reçoit la chaîne cryptée dans le champ data du payload, la déchiffre et la substitue dans les champs de la notification. La clé utilisateur peut être obtenue depuis Keychain après authentification.
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 clé de déchiffrement ne doit pas être stockée dans le code de l'extension ou dans NSUserDefaults. Utilisez iOS Keychain avec accès via App Group pour que l'application et l'extension puissent lire la clé. Utilisez Security.framework avec l'algorithme AES-256-GCM pour la génération de clés sur le client.
L'utilisation la plus courante de Notification Service Extension est le téléchargement d'images, de GIF et de vidéos pour affichage dans la notification. Le serveur envoie une URL de fichier multimédia et l'extension la télécharge, la sauvegarde dans un répertoire temporaire et crée un UNNotificationAttachment.
L'extension reçoit l'URL de l'image depuis le champ payload de la notification. En utilisant URLSession, l'extension télécharge le fichier dans un répertoire temporaire. Une fois le téléchargement terminé, un UNNotificationAttachment avec l'URL locale est créé. La pièce jointe est passée au contenu modifié. iOS affiche automatiquement l'image dans l'interface standard ou dans une 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 supporte les formats suivants pour l'affichage dans les notifications : JPEG, PNG, GIF (statiques), vidéo MPEG-4 jusqu'à 50 Mo. Pour les fichiers audio, MP3, AAC et ALAC sont supportés. Important : tous les fichiers multimédia doivent être téléchargés dans la limite des 30 secondes. Pour les fichiers volumineux, il est recommandé de recadrer côté serveur ou d'utiliser un chargement progressif.
La gestion de la limite de 30 secondes est une tâche clé lors du développement de Notification Service Extension. Si l'extension ne termine pas le traitement à temps, le système appelle serviceExtensionTimeWillExpire et affiche le contenu d'origine. Des scénarios de repli doivent être prévus pour chaque type de traitement.
Divisez les tâches par priorité. Effectuez d'abord les modifications critiques (déchiffrement, localisation de base). Les améliorations optionnelles (téléchargement d'images, enrichissement de texte) viennent ensuite. Utilisez URLSession avec des délais d'attente pour les requêtes réseau afin de ne pas dépenser toute la limite sur une seule opération.
Si le téléchargement d'image échoue ou si le déchiffrement du payload retourne une erreur, l'extension doit appeler contentHandler avec le contenu d'origine. Ne terminez jamais l'extension sans appeler contentHandler — cela entraîne la perte de la notification. Un repli sécurisé doit toujours être prévu dans le code de l'extension.
override func didReceive(
request: UNNotificationRequest,
withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
let content = (request.content.mutableCopy()
as? UNMutableNotificationContent) ?? request.content
// Tâche critique : déchiffrement
var decryptedContent = tryDecryptPayload(content)
// Tâche optionnelle : médias
guard let mediaUrl = decryptedContent.userInfo["media_url"]
as? String else {
handler(decryptedContent)
return
}
downloadAndAttachMedia(
content: decryptedContent,
mediaUrl: mediaUrl,
handler: handler
)
}
Pour tester Notification Service Extension, utilisez Xcode : sélectionnez la cible de l'extension, exécutez sur le simulateur et envoyez une notification push via le terminal ou Firebase Console. Enregistrez chaque étape du traitement avec os_log — cela aide à diagnostiquer les problèmes de temporisation et de téléchargement.
Foire aux questions
Le système appelle serviceExtensionTimeWillExpire, puis affiche la notification d'origine sans modification. Tous les fichiers téléchargés et modifications sont abandonnés.
Oui, si vous appelez contentHandler avec un contenu vide (UNNotificationContent avec des champs vides), la notification ne sera pas affichée. Cela est utilisé pour filtrer les notifications spam ou les données incorrectes.
Le jeton peut être passé dans le userInfo du payload de la notification ou obtenu depuis Keychain via App Group. Il n'est pas recommandé de stocker les jetons dans UserDefaults de l'extension.
L'extension doit être signée avec le même certificat de développeur que l'application principale. Pour la production, un certificat de production avec la capacité Push Notifications activée est requis.
Connectez l'appareil à Xcode, sélectionnez la cible de l'extension dans le schéma d'exécution et envoyez une notification push via Firebase Console. Les points d'arrêt dans l'extension fonctionnent de la même manière que dans l'application principale.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi