Notification Service Extension — είναι μια επέκταση iOS που υποκλέπτει την push ειδοποίηση πριν από την εμφάνισή της στον χρήστη και επιτρέπει την τροποποίηση του περιεχομένου. Η επέκταση μπορεί να αποκρυπτογραφήσει κρυπτογραφημένα δεδομένα, να κατεβάσει συνημμένα πολυμέσων, να αλλάξει κείμενο ή να προσθέσει προσαρμοσμένα πεδία. Σύμφωνα με το Apple Developer, 2025, το Notification Service Extension έχει έως 30 δευτερόλεπτα για να εκτελέσει την εργασία στο παρασκήνιο.
Κύρια
Notification Service Extension — είναι μια επέκταση εφαρμογής στο iOS που εκτελείται πριν από την εμφάνιση της push ειδοποίησης. Επιτρέπει στον διακομιστή να στέλνει ελάχιστο payload, και η επέκταση να το συμπληρώνει με περιεχόμενο: να κατεβάζει εικόνες, να αποκρυπτογραφεί δεδομένα, να αντικαθιστά κείμενο. Ο χρήστης βλέπει την έτοιμη, επεξεργασμένη ειδοποίηση.
Όταν το iOS λαμβάνει μια push ειδοποίηση, το σύστημα ελέγχει την ύπαρξη επέκτασης για αυτήν την εφαρμογή. Εάν η επέκταση είναι καταχωρημένη, το iOS την εκκινεί σε μια διαδικασία παρασκηνίου και μεταδίδει το περιεχόμενο της ειδοποίησης μέσω της μεθόδου didReceive(_:withContentHandler:). Η επέκταση επεξεργάζεται το περιεχόμενο και καλεί το contentHandler με το τροποποιημένο περιεχόμενο. Εάν η επέκταση δεν προλάβει εντός 30 δευτερολέπτων, το σύστημα εμφανίζει την αρχική ειδοποίηση.
Το Service Extension είναι απαραίτητο σε σενάρια όπου το περιεχόμενο της ειδοποίησης απαιτεί επεξεργασία στη συσκευή. Ασφαλείς επικοινωνίες: ο διακομιστής στέλνει κρυπτογραφημένο payload, η επέκταση το αποκρυπτογραφεί τοπικά. Πλούσιες ειδοποιήσεις πολυμέσων: ο διακομιστής στέλνει URL εικόνας, η επέκταση το κατεβάζει και το επισυνάπτει. Δυναμική τοπικοποίηση: η επέκταση αντικαθιστά το κείμενο στη γλώσσα της συσκευής.
| Σενάριο | Χωρίς επέκταση | Με επέκταση |
|---|---|---|
| Εικόνα | Δεν υποστηρίζεται | Λήψη και εμφάνιση |
| Κρυπτογράφηση | Ο διακομιστής κρατά το κλειδί | Αποκρυπτογράφηση στη συσκευή |
| Κείμενο | Σταθερό στον διακομιστή | Δυναμική αντικατάσταση |
| Επικύρωση | Δεν ελέγχεται | Ακύρωση κακόβουλων ειδοποιήσεων |
Το Notification Service Extension λειτουργεί σε περιορισμένο περιβάλλον. Μέγιστος χρόνος εκτέλεσης — 30 δευτερόλεπτα. Η επέκταση δεν έχει πρόσβαση στην κύρια αποθήκευση της εφαρμογής (εκτός από App Group). Το μέγεθος της επέκτασης περιορίζεται στα 50 MB. Σε υπέρβαση χρόνου, το σύστημα καλεί το contentHandler με το αρχικό περιεχόμενο και όλες οι αλλαγές χάνονται.
Στο Xcode, το Notification Service Extension προστίθεται δημιουργώντας ένα νέο target τύπου Notification Service Extension. Το Xcode δημιουργεί ένα πρότυπο κλάσης NotificationService που κληρονομεί από το UNNotificationServiceExtension, με δύο μεθόδους: didReceive και serviceExtensionTimeWillExpire.
Στο Xcode επιλέξτε File → New → Target → Notification Service Extension. Καθορίστε το όνομα (π.χ. PushNotificationService) και τη γλώσσα Swift. Βεβαιωθείτε ότι το target προστέθηκε στην κύρια εφαρμογή και έχει σωστή υπογραφή. Μετά τη δημιουργία, θα δημιουργηθεί η κλάση NotificationService.swift με βασική υλοποίηση.
Το Info.plist της επέκτασης περιέχει το κλειδί NSExtension με υποκλειδιά NSExtensionPointIdentifier (com.apple.usernotifications.service) και NSExtensionPrincipalClass (το όνομα του ελεγκτή σας). Προαιρετικά μπορεί να καθοριστεί NSExtensionAttributes με κανόνες ενεργοποίησης της επέκτασης. Αυτές οι ρυθμίσεις δημιουργούνται αυτόματα από το Xcode.
Η βασική υλοποίηση παρακάμπτει τη didReceive, τροποποιεί το περιεχόμενο της ειδοποίησης και καλεί το contentHandler. Εάν η επεξεργασία διαρκεί πολύ, καλείται η serviceExtensionTimeWillExpire, όπου πρέπει να ολοκληρωθεί η εργασία με την τρέχουσα κατάσταση.
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 = "[Επεξεργάστηκε] \(bestAttemptContent.title)"
contentHandler?(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler,
let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
Μία από τις βασικές εφαρμογές του Service Extension είναι η αποκρυπτογράφηση του περιεχομένου της ειδοποίησης στη συσκευή. Ο διακομιστής στέλνει κρυπτογραφημένο payload, και η επέκταση το αποκρυπτογραφεί χρησιμοποιώντας ένα κλειδί που είναι αποθηκευμένο στο Keychain ή στο App Group. Αυτό εγγυάται ότι το περιεχόμενο δεν μπορεί να υποκλαπεί κατά τη μεταφορά.
Ο διακομιστής κρυπτογραφεί το σώμα της ειδοποίησης χρησιμοποιώντας συμμετρικό κλειδί (AES-256). Το κλειδί κρυπτογράφησης συμφωνείται εκ των προτέρων μεταξύ πελάτη και διακομιστή. Η επέκταση λαμβάνει κρυπτογραφημένη συμβολοσειρά στο πεδίο data του payload, την αποκρυπτογραφεί και την τοποθετεί στα πεδία της ειδοποίησης. Το κλειδί χρήστη μπορεί να ληφθεί από το Keychain μετά την αυθεντικοποίηση.
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)
}
Το κλειδί αποκρυπτογράφησης δεν πρέπει να αποθηκεύεται στον κώδικα της επέκτασης ή στο NSUserDefaults. Χρησιμοποιήστε iOS Keychain με πρόσβαση μέσω App Group, ώστε τόσο η εφαρμογή όσο και η επέκταση να μπορούν να διαβάσουν το κλειδί. Για τη δημιουργία κλειδιού στην πλευρά του πελάτη, χρησιμοποιήστε το Security.framework με αλγόριθμο AES-256-GCM.
Η πιο συχνή χρήση του Notification Service Extension — λήψη εικόνων, GIF και βίντεο για επακόλουθη εμφάνιση στην ειδοποίηση. Ο διακομιστής στέλνει το URL του αρχείου πολυμέσου, και η επέκταση το κατεβάζει, το αποθηκεύει σε προσωρινό κατάλογο και δημιουργεί UNNotificationAttachment.
Η επέκταση λαμβάνει το URL της εικόνας από το πεδίο payload της ειδοποίησης. Χρησιμοποιώντας το URLSession, η επέκταση κατεβάζει το αρχείο σε προσωρινό κατάλογο. Μετά την ολοκλήρωση της λήψης, δημιουργείται UNNotificationAttachment με το τοπικό URL. Το συνημμένο μεταδίδεται στο τροποποιημένο περιεχόμενο. Το iOS αυτόματα εμφανίζει την εικόνα στην τυπική διεπαφή ή στο 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 υποστηρίζει τις ακόλουθες μορφές για εμφάνιση σε ειδοποιήσεις: JPEG, PNG, GIF (στατικά), βίντεο MPEG-4 έως 50 MB. Για αρχεία ήχου υποστηρίζονται MP3, AAC και ALAC. Σημαντικό: όλα τα αρχεία πολυμέσων πρέπει να ληφθούν εντός του ορίου των 30 δευτερολέπτων. Για μεγάλα αρχεία, συνιστάται περικοπή από τον διακομιστή ή προοδευτική λήψη.
Διαχείριση του ορίου των 30 δευτερολέπτων — βασικό καθήκον στην ανάπτυξη του Notification Service Extension. Εάν η επέκταση δεν ολοκληρώσει την επεξεργασία, το σύστημα καλεί το serviceExtensionTimeWillExpire και εμφανίζει το αρχικό περιεχόμενο. Πρέπει να προβλέπονται σενάρια εφεδρείας για κάθε τύπο επεξεργασίας.
Χωρίστε τις εργασίες ανά προτεραιότητα. Οι κρίσιμες τροποποιήσεις (αποκρυπτογράφηση, βασική τοπικοποίηση) εκτελούνται πρώτα. Οι προαιρετικές βελτιώσεις (λήψη εικόνων, εμπλουτισμός κειμένου) — σε δεύτερη φάση. Χρησιμοποιήστε URLSession με χρονικά όρια για αιτήματα δικτύου, για να μην εξαντλήσετε ολόκληρο το όριο σε μία λειτουργία.
Εάν η λήψη εικόνας απέτυχε ή η αποκρυπτογράφηση payload επέστρεψε σφάλμα, η επέκταση πρέπει να καλέσει το contentHandler με το αρχικό περιεχόμενο. Μην τερματίζετε ποτέ την επέκταση χωρίς να καλέσετε το contentHandler — αυτό οδηγεί σε απώλεια της ειδοποίησης. Ασφαλής εφεδρεία πρέπει πάντα να προβλέπεται στον κώδικα της επέκτασης.
override func didReceive(
request: UNNotificationRequest,
withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
let content = (request.content.mutableCopy()
as? UNMutableNotificationContent) ?? request.content
// Κρίσιμη εργασία: αποκρυπτογράφηση
var decryptedContent = tryDecryptPayload(content)
// Προαιρετική εργασία: πολυμέσα
guard let mediaUrl = decryptedContent.userInfo["media_url"]
as? String else {
handler(decryptedContent)
return
}
downloadAndAttachMedia(
content: decryptedContent,
mediaUrl: mediaUrl,
handler: handler
)
}
Για τη δοκιμή του Notification Service Extension χρησιμοποιήστε Xcode: επιλέξτε το target της επέκτασης, εκτελέστε στον προσομοιωτή και στείλτε push ειδοποίηση μέσω τερματικού ή Firebase Console. Καταγράψτε κάθε στάδιο επεξεργασίας μέσω os_log — αυτό βοηθά στη διάγνωση προβλημάτων χρονισμού και σφαλμάτων φόρτωσης.
Συχνές Ερωτήσεις
Το σύστημα θα καλέσει το serviceExtensionTimeWillExpire, στη συνέχεια θα εμφανίσει την αρχική ειδοποίηση χωρίς αλλαγές. Όλα τα ληφθέντα αρχεία και τροποποιήσεις θα απορριφθούν.
Ναι, εάν καλέσετε το contentHandler με κενό περιεχόμενο (UNNotificationContent με κενά πεδία), η ειδοποίηση δεν θα εμφανιστεί. Αυτό χρησιμοποιείται για φιλτράρισμα spam ειδοποιήσεων ή λανθασμένων δεδομένων.
Το διακριτικό μπορεί να μεταδοθεί στο userInfo του payload της ειδοποίησης ή να ληφθεί από το Keychain μέσω App Group. Δεν συνιστάται η αποθήκευση διακριτικών στο UserDefaults της επέκτασης.
Η επέκταση πρέπει να υπογράφεται με το ίδιο πιστοποιητικό προγραμματιστή με την κύρια εφαρμογή. Για παραγωγή απαιτείται πιστοποιητικό παραγωγής με ενεργοποιημένη τη δυνατότητα Push Notifications.
Συνδέστε τη συσκευή στο Xcode, επιλέξτε το target της επέκτασης στο σχήμα εκκίνησης και στείλτε push ειδοποίηση μέσω Firebase Console. Τα Breakpoints στην επέκταση λειτουργούν όπως στην κύρια εφαρμογή.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης