Notification Service Extension: обрада садржаја пре приказивања на iOS-у

Аутор: IT Sectr Објављено: 2026-03-21 Време читања: 8 мин

Notification Service Extension — је iOS екстензија која пресреће push обавештење пре његовог приказивања кориснику и омогућава модификацију садржаја. Екстензија може да дешифрује шифроване податке, преузме медијске прилоге, измени текст или дода прилагођена поља. Према Apple Developer, 2025, Notification Service Extension има до 30 секунди за извршавање задатка у позадини.

Главно

  • Notification Service Extension — iOS екстензија за обраду push обавештења пре приказивања.
  • Екстензија наслеђује UNNotificationServiceExtension и имплементира метод didReceive.
  • Доступно до 30 секунди позадинског извршавања за преузимање и обраду података.
  • Основни сценарији: дешифровање payload-а, преузимање слика и видеа, валидација садржаја.
  • Екстензија може одложити приказивање обавештења или га потпуно отказати путем contentHandler-а.

Шта је Notification Service Extension

Notification Service Extension — је app екстензија у iOS-у која се покреће пре приказивања push обавештења. Омогућава серверу да шаље минимални payload, а екстензија да га допуни садржајем: преузме слике, дешифрује податке, замени текст. Корисник види већ готово, обрађено обавештење.

Како ово ради

Када iOS прими push обавештење, систем проверава присуство екстензије за дату апликацију. Ако је екстензија регистрована, iOS је покреће у позадинском процесу и прослеђује садржај обавештења кроз метод didReceive(_:withContentHandler:). Екстензија обрађује садржај и позива contentHandler са измењеним садржајем. Ако екстензија не стигне у року од 30 секунди, систем приказује оригинално обавештење.

Када користити Service Extension

Service Extension је неопходан у сценаријима где садржај обавештења захтева обраду на уређају. Сигурне комуникације: сервер шаље шифровани payload, екстензија га дешифрује локално. Богата медијска обавештења: сервер шаље URL слике, екстензија преузима и прилаже га. Динамичка локализација: екстензија замењује текст на језику уређаја.

СценаријБез екстензијеСа екстензијом
СликаНије подржаноПреузима се и приказује
ШифровањеСервер чува кључДешифровање на уређају
ТекстЧврсто постављен на серверуДинамичка замена
ВалидацијаНе проверава сеОтказивање злонамерних обавештења

Ограничења и време извршавања

Notification Service Extension ради у ограниченом окружењу. Максимално време извршавања — 30 секунди. Екстензија нема приступ главном складишту апликације (осим App Group-а). Величина екстензије је ограничена на 50 MB. При прекорачењу времена, систем позива contentHandler са оригиналним садржајем и све измене се губе.

Креирање екстензије и подешавање Info.plist

У Xcode-у, Notification Service Extension се додаје креирањем новог target-а типа Notification Service Extension. Xcode генерише шаблон класе NotificationService која наслеђује UNNotificationServiceExtension, са два метода: didReceive и serviceExtensionTimeWillExpire.

Додавање target-а у пројекат

У Xcode-у изаберите File → New → Target → Notification Service Extension. Наведите име (нпр. PushNotificationService) и језик Swift. Уверите се да је target додат главној апликацији и да има исправан потпис. Након креирања, генерисаће се класа NotificationService.swift са основном имплементацијом.

Структура Info.plist екстензије

Info.plist екстензије садржи кључ NSExtension са подкључевима NSExtensionPointIdentifier (com.apple.usernotifications.service) и NSExtensionPrincipalClass (име вашег контролера). Опционо се може навести NSExtensionAttributes са правилима активације екстензије. Ова подешавања Xcode генерише аутоматски.

Пример основне екстензије

Основна имплементација преписује didReceive, мења садржај обавештења и позива contentHandler. Ако обрада траје предуго, позива се serviceExtensionTimeWillExpire, где треба завршити рад са тренутним стањем.

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 = "[Обрађено] \(bestAttemptContent.title)"
            contentHandler?(bestAttemptContent)
        }
    }

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

Дешифровање шифрованог payload-а

Једна од кључних примена Service Extension-а је дешифровање садржаја обавештења на уређају. Сервер шаље шифровани payload, а екстензија га дешифрује користећи кључ ускладиштен у Keychain-у или App Group-у. Ово гарантује да садржај није доступан за пресретање током преноса.

Архитектура сигурне доставе

Сервер шифрује тело обавештења користећи симетрични кључ (AES-256). Кључ за шифровање је унапред договорен између клијента и сервера. Екстензија добија шифровани низ у пољу data payload-а, дешифрује га и поставља у поља обавештења. Кориснички кључ се може добити из Keychain-а након аутентификације.

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

Сигурно чување кључева

Кључ за дешифровање не треба чувати у коду екстензије или 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-у.

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

Подржани медијски формати

iOS подржава следеће формате за приказивање у обавештењима: JPEG, PNG, GIF (статични), MPEG-4 видео до 50 MB. За аудио фајлове подржани су MP3, AAC и ALAC. Важно: сви медијски фајлови морају бити преузети у оквиру 30-секундног ограничења. За велике фајлове препоручује се серверско сечење или прогресивно преузимање.

Управљање временом и fallback сценарији

Управљање 30-секундним ограничењем — кључни задатак при развоју Notification Service Extension-а. Ако екстензија не заврши обраду на време, систем позива serviceExtensionTimeWillExpire и приказује оригинални садржај. Потребно је предвидети fallback сценарије за сваки тип обраде.

Стратегија приоритета

Поделите задатке по приоритетима. Критичне измене (дешифровање, основна локализација) извршите прво. Опциона побољшања (преузимање слика, обогаћивање текста) — у другом реду. Користите URLSession са тајмаутима за мрежне захтеве, како не бисте потрошили цело ограничење на једну операцију.

Fallback при грешкама

Ако преузимање слике није успело или дешифровање payload-а врати грешку, екстензија треба да позове contentHandler са оригиналним садржајем. Никада не завршавајте екстензију без позивања contentHandler-а — то доводи до губитка обавештења. Сигуран fallback увек треба да буде предвиђен у коду екстензије.

swift
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 — ово помаже у дијагностици проблема са временом и грешкама учитавања.

Често постављана питања

Шта се дешава ако екстензија не стигне у року од 30 секунди?

Систем ће позвати serviceExtensionTimeWillExpire, након чега ће приказати оригинално обавештење без измена. Сви преузети фајлови и модификације биће одбачени.

Може ли се отказати приказивање обавештења из екстензије?

Да, ако позовете contentHandler са празним садржајем (UNNotificationContent са празним пољима), обавештење неће бити приказано. Ово се користи за филтрирање спам обавештења или нетачних података.

Како проследити токен ауторизације за преузимање медија?

Токен се може проследити у userInfo payload-а обавештења или добити из Keychain-а преко App Group-а. Не препоручује се чување токена у UserDefaults-у екстензије.

Да ли је потребна посебна конфигурација сертификата за екстензију?

Екстензија мора бити потписана истим развојним сертификатом као и главна апликација. За продукцију је потребан продукциони сертификат са укљученим capability Push Notifications.

Како отклонити грешке у екстензији на стварном уређају?

Повежите уређај са Xcode-ом, изаберите target екстензије у шеми покретања и пошаљите push обавештење преко Firebase Console-е. Breakpoints у екстензији раде исто као у главној апликацији.

Резиме

  • Notification Service Extension — iOS екстензија за позадинску обраду push обавештења пре приказивања.
  • Максимално време извршавања — 30 секунди, након чега систем приказује оригинални садржај.
  • Основне примене: дешифровање payload-а, преузимање медија, валидација и локализација садржаја.
  • Екстензија наслеђује UNNotificationServiceExtension са методима didReceive и serviceExtensionTimeWillExpire.
  • За преузимање медија користите URLSession, за чување кључева — iOS Keychain.
  • Увек предвидите fallback — позовите contentHandler са оригиналним садржајем при грешкама.
  • Комбинујте Service Extension са Content Extension-ом за потпуну контролу над обавештењима.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође