Notification Service Extension je rozšíření iOS, které zachytí push oznámení ihned po přijetí, ale před zobrazením uživateli. Rozšíření může dešifrovat zašifrovaný payload, stáhnout a připojit mediální soubor, změnit text nebo titulek oznámení v reálném čase. Podle Apple Developer Documentation (2025) musí server pro aktivaci rozšíření odeslat klíč mutable-content:1 v atributech oznámení — to je jediná podmínka pro spuštění UNNotificationServiceExtension.
Hlavní body
Notification Service Extension je rozšíření aplikace v iOS, které na straně zařízení zachytí příchozí push oznámení a umožňuje změnit jeho obsah dříve, než jej uživatel uvidí. Jedná se o jediný typ rozšíření oznámení, který pracuje s obsahem, nikoli se zobrazením.
Klíčový rozdíl od Notification Content Extension: Service Extension pracuje před zobrazením oznámení a může změnit titulek, tělo, zvukový soubor a přílohy. Content Extension pracuje po zobrazení a spravuje pouze vizuální prezentaci hotového oznámení. Tato dvě rozšíření mohou spolupracovat: Service Extension stáhne obrázek a Content Extension jej zobrazí ve vlastním rozhraní.
Rozšíření se automaticky aktivuje při přijetí push oznámení s atributem mutable-content:1 ve slovníku aps. iOS spustí rozšíření na pozadí, předá mu původní UNNotificationRequest a očekává upravenou verzi k zobrazení.
UNNotificationServiceExtension obdrží úplný UNNotificationRequest s původním obsahem. Rozšíření může upravit libovolná pole UNNotificationContent: title, subtitle, body, userInfo, attachments a sound. Změny se aplikují před zobrazením oznámení.
Dešifrování obsahu — pokud push oznámení obsahuje zašifrovaný payload, rozšíření jej dešifruje před zobrazením. Stahování médií — připojení obrázku nebo videa k oznámení. Lokalizace — přizpůsobení textu oznámení regionálním nastavením zařízení. Obohacení dat — přidání dalších informací z místního úložiště nebo mezipaměti.
Podle Apple je nejčastějším scénářem mezi aplikacemi stahování obrázků pro bohatá mediální oznámení. Server odešle URL obrázku v payloadu, rozšíření jej stáhne do dočasného adresáře a vytvoří UNNotificationAttachment, který systém zobrazí ve standardním nebo vlastním rozhraní.
Rozšíření může zcela přepsat text oznámení, nahradit titulek nebo přidat subtitle. Například aplikace pro zasílání zpráv může obdržet zašifrované oznámení, dešifrovat jej v rozšíření a zobrazit čitelný text. Nebo zpravodajská aplikace může přidat kategorii zprávy do podtitulku před zobrazením.
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
let content = request.content.mutableCopy()
as! UNMutableNotificationContent
if let imageURL = content.userInfo["media-url"]
as? String {
downloadAndAttach(imageURL: imageURL,
content: content,
handler: contentHandler)
}
}
UNNotificationServiceExtension — základní třída, od které Service Extension dědí. Třída definuje dvě metody životního cyklu: didReceive(_:withContentHandler:) — hlavní metodu zpracování, a serviceExtensionTimeWillExpire() — obsluhu vypršení času.
didReceive(_:withContentHandler:) je volána při přijetí oznámení. Rozšíření obdrží UNNotificationRequest a closure contentHandler, které musí být voláno s upraveným UNMutableNotificationContent. Rozšíření je povinno zavolat contentHandler — pokud tak neučiní, iOS po vypršení časového limitu zobrazí původní oznámení.
Důležité: rozšíření může zpracovávat pouze jedno oznámení najednou. Pokud dorazí několik oznámení současně, iOS vytvoří samostatné instance rozšíření pro každé z nich. Globální stav nelze použít pro sekvenční zpracování.
serviceExtensionTimeWillExpire() je volána systémem, když zbývající doba provádění končí. V této metodě je třeba okamžitě zavolat contentHandler s obsahem, který je v danou chvíli připraven — i když se mediální soubor ještě nestáhl. Pokud není contentHandler v této metodě volán, iOS zobrazí původní oznámení.
Doporučuje se v této metodě uchovávat minimálně přijatelný obsah — například oznámení s textem a titulkem, ale bez obrázku, jehož stažení nebylo včas dokončeno.
UNNotificationAttachment — objekt vytvořený rozšířením pro připojení mediálního souboru k oznámení. Rozšíření stáhne soubor ze sítě, uloží jej do dočasného adresáře a vytvoří UNNotificationAttachment s určením typu obsahu.
UNNotificationAttachment se vytváří pomocí inicializátoru init(identifier:url:options:). URL musí odkazovat na místní soubor v dočasném adresáři přístupném rozšíření. Po vytvoření se příloha přidá do pole attachments v UNMutableNotificationContent.
Apple doporučuje použití URLSession s konfigurací na pozadí pro stahování — při použití standardního URLSession stahování blokuje vlákno a spotřebovává čas z 30sekundového limitu. URLSession na pozadí pokračuje ve stahování i po ukončení rozšíření a výsledek lze použít při příštím spuštění.
Pokud server odesílá zašifrované oznámení, rozšíření musí dešifrovat payload před voláním contentHandler. Dešifrování obvykle zahrnuje vyžádání klíče z Keychain nebo App Group, dešifrování přes CommonCrypto a nahrazení body nebo userInfo oznámení. Při chybě dešifrování je třeba zavolat contentHandler s původním obsahem — aby uživatel alespoň viděl, že oznámení dorazilo, i když je nečitelné.
func downloadAndAttach(
imageURL: String,
content: UNMutableNotificationContent,
handler: @escaping (UNNotificationContent) -> Void
) {
let task = URLSession.shared.dataTask(with:
URL(string: imageURL)!) { data, _, _ in
let url = FileManager.default
.temporaryDirectory
.appendingPathComponent("image.jpg")
try? data?.write(to: url)
let attachment = try? UNNotificationAttachment(
identifier: "image", url: url)
content.attachments = [attachment].compactMap { $0 }
handler(content)
}
task.resume()
}
Notification Service Extension pracuje v přísných časových rámcích. iOS přiděluje pevnou dobu provádění — přibližně 30 sekund od okamžiku aktivace. Pokud rozšíření v této době nezavolá contentHandler, systém proces násilně ukončí a zobrazí původní oznámení bez změn.
Doporučuje se implementovat víceúrovňový fallback: nejprve zkusit stáhnout média, při úspěchu — zavolat contentHandler s plným obsahem; při neúspěchu — zavolat contentHandler s textem, ale bez médií; při kritické chybě — předat původní obsah. Tento přístup zaručuje, že uživatel vždy uvidí oznámení, ne prázdnou obrazovku.
Podle Apple je nejčastější příčinou časových limitů stahování velkých mediálních souborů při pomalém připojení. Pro snížení rizika se doporučuje optimalizovat velikost obrázků na serveru — odesílat náhledy do 300 KB namísto plného rozlišení. Obrázky v plném rozlišení je vhodné stahovat až při otevření aplikace.
Pro sledování časových limitů a chyb rozšíření lze použít os_log pro zápis diagnostických zpráv do Unified Logging System. Přestože je přímé protokolování do souboru v rozšíření obtížné, os_log umožňuje analýzu výkonu přes Console.app na vývojářském zařízení. Apple doporučuje přidávat metriky při každém volání didReceive — dobu stahování, velikost souboru, výsledek operace.
override func serviceExtensionTimeWillExpire() {
let fallback = bestEffortContent as?
UNMutableNotificationContent
?? request.content.mutableCopy()
as! UNMutableNotificationContent
contentHandler(fallback)
}
Často kladené otázky
Server přidá klíč mutable-content:1 do aps slovníku push oznámení. Bez tohoto parametru systém rozšíření ignoruje a zobrazí standardní oznámení.
Ne. mutable-content:1 je povinnou podmínkou aktivace Service Extension. Pokud klíč chybí nebo je nastaven na 0, oznámení se zobrazí bez volání rozšíření.
iOS násilně ukončí rozšíření a zobrazí původní oznámení beze změn. Abyste tomu předešli, implementujte serviceExtensionTimeWillExpire() s minimálně přijatelným obsahem.
Prostřednictvím App Group (sdíleného UserDefaults nebo souboru) nebo Keychain se sdíleným přístupem mezi aplikací a rozšířením. Přímé předávání klíčů v payloadu oznámení není bezpečné.
Až 4 přílohy na jedno oznámení, každá do 50 MB. Celková velikost příloh ovlivňuje dobu stahování — čím více souborů, tím vyšší riziko časového limitu.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také