Notification Service Extension: procesarea conținutului înainte de afișare pe iOS

Autor: IT Sectr Publicat: 2026-03-21 Timp de citire: 8 min

Notification Service Extension — este o extensie iOS care interceptează notificarea push înainte de afișarea ei utilizatorului și permite modificarea conținutului. Extensia poate decripta date criptate, descărca atașamente media, modifica textul sau adăuga câmpuri personalizate. Conform Apple Developer, 2025, Notification Service Extension are până la 30 de secunde pentru a executa sarcina în fundal.

Principalele

  • Notification Service Extension — extensie iOS pentru procesarea notificării push înainte de afișare.
  • Extensia moștenește de la UNNotificationServiceExtension și implementează metoda didReceive.
  • Disponibil până la 30 de secunde de execuție în fundal pentru descărcarea și procesarea datelor.
  • Scenarii principale: decriptarea payloadului, descărcarea imaginilor și videourilor, validarea conținutului.
  • Extensia poate amâna afișarea notificării sau o poate anula complet prin contentHandler.

Ce este Notification Service Extension

Notification Service Extension — este o extensie de aplicație în iOS care se lansează înainte de afișarea notificării push. Permite serverului să trimită un payload minim, iar extensia să îl completeze cu conținut: să descarce imagini, să decripteze date, să înlocuiască textul. Utilizatorul vede notificarea deja pregătită, procesată.

Cum funcționează

Când iOS primește o notificare push, sistemul verifică prezența extensiei pentru această aplicație. Dacă extensia este înregistrată, iOS o lansează într-un proces de fundal și transmite conținutul notificării prin metoda didReceive(_:withContentHandler:). Extensia procesează conținutul și apelează contentHandler cu conținutul modificat. Dacă extensia nu reușește în 30 de secunde, sistemul afișează notificarea originală.

Când să utilizați Service Extension

Service Extension este necesară în scenariile în care conținutul notificării necesită procesare pe dispozitiv. Comunicații sigure: serverul trimite un payload criptat, extensia îl decriptează local. Notificări media bogate: serverul trimite un URL de imagine, extensia îl descarcă și îl atașează. Localizare dinamică: extensia înlocuiește textul în limba dispozitivului.

ScenariuFără extensieCu extensie
ImagineNu este suportatSe descarcă și se afișează
CriptareServerul păstrează cheiaDecriptare pe dispozitiv
TextSetat rigid pe serverÎnlocuire dinamică
ValidareNu se verificăAnularea notificărilor malițioase

Limitări și timp de execuție

Notification Service Extension funcționează într-un mediu limitat. Timpul maxim de execuție — 30 de secunde. Extensia nu are acces la stocarea principală a aplicației (cu excepția App Group). Dimensiunea extensiei este limitată la 50 MB. La depășirea timpului, sistemul apelează contentHandler cu conținutul original și toate modificările se pierd.

Crearea extensiei și configurarea Info.plist

În Xcode, Notification Service Extension se adaugă prin crearea unui nou target de tip Notification Service Extension. Xcode generează un șablon de clasă NotificationService care moștenește UNNotificationServiceExtension, cu două metode: didReceive și serviceExtensionTimeWillExpire.

Adăugarea targetului în proiect

În Xcode alegeți File → New → Target → Notification Service Extension. Specificați numele (de exemplu, PushNotificationService) și limbajul Swift. Asigurați-vă că targetul a fost adăugat la aplicația principală și are semnătura corectă. După creare, va fi generată clasa NotificationService.swift cu implementarea de bază.

Structura Info.plist a extensiei

Info.plist al extensiei conține cheia NSExtension cu subcheile NSExtensionPointIdentifier (com.apple.usernotifications.service) și NSExtensionPrincipalClass (numele controlerului). Opțional, se poate specifica NSExtensionAttributes cu regulile de activare ale extensiei. Aceste setări sunt generate automat de Xcode.

Exemplu de extensie de bază

Implementarea de bază suprascrie didReceive, modifică conținutul notificării și apelează contentHandler. Dacă procesarea durează prea mult, se apelează serviceExtensionTimeWillExpire, unde trebuie să finalizați lucrul cu starea curentă.

swift
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 = "[Procesat] \(bestAttemptContent.title)"
            contentHandler?(bestAttemptContent)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler,
           let bestAttemptContent = bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}

Decriptarea payloadului criptat

Una dintre aplicațiile cheie ale Service Extension este decriptarea conținutului notificării pe dispozitiv. Serverul trimite un payload criptat, iar extensia îl decriptează folosind o cheie stocată în Keychain sau App Group. Aceasta garantează că conținutul nu poate fi interceptat în timpul transmisiei.

Arhitectura livrării sigure

Serverul criptează corpul notificării utilizând o cheie simetrică (AES-256). Cheia de criptare este convenită în prealabil între client și server. Extensia primește un șir criptat în câmpul data al payloadului, îl decriptează și îl plasează în câmpurile notificării. Cheia utilizatorului poate fi obținută din Keychain după autentificare.

swift
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)
}

Stocarea sigură a cheilor

Cheia de decriptare nu trebuie stocată în codul extensiei sau în NSUserDefaults. Utilizați iOS Keychain cu acces prin App Group, astfel încât atât aplicația cât și extensia să poată citi cheia. Pentru generarea cheii pe client, utilizați Security.framework cu algoritmul AES-256-GCM.

Descărcarea și atașarea fișierelor media

Cea mai frecventă utilizare a Notification Service Extension — descărcarea imaginilor, GIF-urilor și videourilor pentru afișarea ulterioară în notificare. Serverul trimite URL-ul fișierului media, iar extensia îl descarcă, îl salvează într-un director temporar și creează UNNotificationAttachment.

Procesul de descărcare și atașare a mediilor

Extensia primește URL-ul imaginii din câmpul payload al notificării. Folosind URLSession, extensia descarcă fișierul într-un director temporar. După finalizarea descărcării, se creează UNNotificationAttachment cu URL-ul local. Atașamentul este transmis în conținutul modificat. iOS afișează automat imaginea în interfața standard sau în Notification Content Extension.

swift
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()
}

Formate media suportate

iOS suportă următoarele formate pentru afișarea în notificări: JPEG, PNG, GIF (statice), video MPEG-4 până la 50 MB. Pentru fișiere audio, sunt suportate MP3, AAC și ALAC. Important: toate fișierele media trebuie descărcate în limita de 30 de secunde. Pentru fișiere mari, se recomandă tăierea pe server sau descărcarea progresivă.

Gestionarea timpului și scenarii de rezervă

Gestionarea limitei de 30 de secunde — sarcina cheie în dezvoltarea Notification Service Extension. Dacă extensia nu reușește să finalizeze procesarea, sistemul apelează serviceExtensionTimeWillExpire și afișează conținutul original. Trebuie prevăzute scenarii de rezervă pentru fiecare tip de procesare.

Strategia priorităților

Împărțiți sarcinile pe priorități. Modificările critice (decriptare, localizare de bază) executați-le în primul rând. Îmbunătățirile opționale (descărcarea imaginilor, îmbogățirea textului) — în al doilea rând. Utilizați URLSession cu timeout pentru cererile de rețea, pentru a nu consuma întreaga limită pe o singură operație.

Scenarii de rezervă la erori

Dacă descărcarea imaginii a eșuat sau decriptarea payloadului a returnat o eroare, extensia trebuie să apeleze contentHandler cu conținutul original. Nu finalizați niciodată extensia fără a apela contentHandler — aceasta duce la pierderea notificării. Rezerva sigură trebuie întotdeauna prevăzută în codul extensiei.

swift
override func didReceive(
    request: UNNotificationRequest,
    withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
    let content = (request.content.mutableCopy()
        as? UNMutableNotificationContent) ?? request.content

    // Sarcină critică: decriptare
    var decryptedContent = tryDecryptPayload(content)

    // Sarcină opțională: media
    guard let mediaUrl = decryptedContent.userInfo["media_url"]
        as? String else {
        handler(decryptedContent)
        return
    }

    downloadAndAttachMedia(
        content: decryptedContent,
        mediaUrl: mediaUrl,
        handler: handler
    )
}

Testarea extensiei

Pentru testarea Notification Service Extension utilizați Xcode: selectați targetul extensiei, rulați pe simulator și trimiteți o notificare push prin terminal sau Firebase Console. Logați fiecare etapă de procesare prin os_log — aceasta ajută la diagnosticarea problemelor de timp și erorilor de încărcare.

Întrebări frecvente

Ce se întâmplă dacă extensia nu se încadrează în 30 de secunde?

Sistemul va apela serviceExtensionTimeWillExpire, după care va afișa notificarea originală fără modificări. Toate fișierele descărcate și modificările vor fi anulate.

Se poate anula afișarea notificării din extensie?

Da, dacă apelați contentHandler cu conținut gol (UNNotificationContent cu câmpuri goale), notificarea nu va fi afișată. Aceasta se utilizează pentru filtrarea notificărilor spam sau a datelor incorecte.

Cum se transmite tokenul de autorizare pentru descărcarea mediilor?

Tokenul poate fi transmis în userInfo al payloadului notificării sau obținut din Keychain prin App Group. Nu se recomandă stocarea tokenurilor în UserDefaults ale extensiei.

Este necesară o configurare specială a certificatelor pentru extensie?

Extensia trebuie să fie semnată cu același certificat de dezvoltator ca și aplicația principală. Pentru producție este necesar certificatul de producție cu capability Push Notifications activată.

Cum se depanează extensia pe un dispozitiv real?

Conectați dispozitivul la Xcode, selectați targetul extensiei în schema de lansare și trimiteți o notificare push prin Firebase Console. Breakpoints în extensie funcționează la fel ca în aplicația principală.

Rezumat

  • Notification Service Extension — extensie iOS pentru procesarea în fundal a notificărilor push înainte de afișare.
  • Timpul maxim de execuție — 30 de secunde, după care sistemul afișează conținutul original.
  • Principalele utilizări: decriptarea payloadului, descărcarea mediilor, validarea și localizarea conținutului.
  • Extensia moștenește de la UNNotificationServiceExtension cu metodele didReceive și serviceExtensionTimeWillExpire.
  • Pentru descărcarea mediilor utilizați URLSession, pentru stocarea cheilor — iOS Keychain.
  • Prevădeți întotdeauna o rezervă — apelați contentHandler cu conținutul original în caz de erori.
  • Combinați Service Extension cu Content Extension pentru control complet asupra notificărilor.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și