Push notifikácie v .NET MAUI 10: FCM, APNs a lokálne notifikácie (2026)
Praktický návod, ako nastaviť push notifikácie v .NET MAUI 10: Firebase Cloud Messaging pre Android aj iOS, APNs s P8 kľúčmi, deep linking cez Shell, odosielanie z .NET backendu cez FirebaseAdmin SDK a lokálne pripomienky.
Push notifikácie v .NET MAUI sa najlepšie implementujú kombináciou Firebase Cloud Messaging (FCM) pre Android aj iOS a knižnice Plugin.LocalNotification pre lokálne pripomienky. V tomto sprievodcovi prejdeme inštaláciou Plugin.Firebase v .NET MAUI 10, konfiguráciou Androidu cez google-services.json, registráciou APNs tokenov na iOS, odosielaním správ z .NET backendu cez FirebaseAdmin SDK, spracovaním payloadu v popredí aj na pozadí, deep linkmi a tiež Azure Notification Hubs ako škálovateľnou alternatívou.
Úprimne, push notifikácie sú jedna z tých vecí, ktoré vyzerajú jednoducho v dokumentácii a potom strávite popoludnie hľadaním, prečo iOS v produkcii mlčí. Pri poslednom projekte som narazil presne na tento prípad (chýbalo mi prepnutie aps-environment), takže tento návod má byť aj zoznamom všetkých grábľov, na ktoré som už šliapol.
Pre cross-platform push notifikácie v .NET MAUI 10 použite Plugin.Firebase.CloudMessaging 3.x, ktoré zjednocuje FCM na Androide aj APNs na iOS cez jediné API.
Apple od júna 2025 vyžaduje JWT-based APNs autentifikáciu s P8 kľúčmi. Staré PEM certifikáty sú deprecated a v produkcii sa neodporúčajú.
Lokálne notifikácie (časovače, pripomienky bez serverového triggeru) rieši Plugin.LocalNotification 11.x, ktorý pridáva podporu pre Android 14 POST_NOTIFICATIONS permission a iOS Focus modes.
Backend odosielanie zvládne FirebaseAdmin NuGet (Google) alebo Azure Notification Hubs, ak potrebujete tag-based broadcast pre milióny zariadení.
Spracovanie payloadu v popredí, na pozadí a po zabití aplikácie sa líši. Pre deep linking použite Shell Routing.RegisterRoute a navigáciu cez Shell.Current.GoToAsync.
Pre testovanie využite Firebase Console → Messaging alebo cURL volania na https://fcm.googleapis.com/v1/projects/{projectId}/messages:send s OAuth2 access tokenom.
Prečo Firebase Cloud Messaging na oboch platformách
Historicky vývojári riešili push notifikácie zvlášť pre každú platformu, teda APNs pre iOS a FCM (predtým GCM) pre Android. Od roku 2024 však Apple oficiálne podporuje doručovanie cez FCM tak, že Firebase backend funguje ako prostredník: vašu správu adresovanú konkrétnemu zariadeniu preposlať na APNs s podpísaným JWT a iOS klientovi doručí push payload. Pre .NET MAUI to znamená, že pomocou jediného plugina Plugin.Firebase.CloudMessaging dostanete jedno API na získanie tokenu, spracovanie správy a odhlásenie z tém. Šetríte si tým duplicitnú údržbu dvoch SDK.
Druhá výhoda je analytika. Firebase Console poskytuje doručovacie metriky (delivery rate, open rate, conversion), A/B testovanie notifikácií a Remote Config v rovnakom dashboarde. Ak používate Google Analytics for Firebase, automaticky uvidíte korelácie medzi push kampaňami a in-app eventmi. Oficiálna dokumentácia FCM popisuje aj limity: payload max 4 KB, najviac 500 príjemcov v jednej multicast správe a TTL do 28 dní.
Tretí dôvod je cena. FCM je zadarmo aj na produkčný objem v rámci Spark plánu, čo je pre väčšinu indie aplikácií a malých firiem viac než dostatočné. Platenú alternatívu (Azure Notification Hubs, OneSignal) zvážte iba ak potrebujete pokročilé segmentácie, audit log alebo on-premise hosting.
Nastavenie .NET MAUI projektu a Firebase
Predpokladám, že máte čerstvý .NET MAUI 10 projekt vytvorený cez dotnet new maui -n PushDemo. Otvorte Firebase Console, vytvorte projekt a v ňom dve aplikácie: Android (package name napríklad com.example.pushdemo) a iOS (rovnaký bundle identifier). Stiahnite si google-services.json do Platforms/Android/ a GoogleService-Info.plist do Platforms/iOS/.
Architektúru a životný cyklus DI v MAUI rozoberá podrobnejšie náš sprievodca MVVM architektúrou v .NET MAUI, kde nájdete vzor, ako registrovať služby ako INotificationRouter a vstrekovať ich do ViewModelov.
Konfigurácia Androidu krok za krokom
Na Androide musíte upraviť AndroidManifest.xml a pridať povolenie POST_NOTIFICATIONS, ktoré je povinné od Androidu 13 (API 33). Bez neho používateľ nikdy nedostane notifikáciu, aj keby bol token registrovaný úplne správne.
Vytvorte notifikačný kanál pri prvom štarte aplikácie. Android 8+ vyžaduje, aby každá notifikácia patrila do kanálu s definovanou dôležitosťou. V MainActivity.OnCreate:
var channel = new NotificationChannel(
"default_channel",
"Všeobecné upozornenia",
NotificationImportance.High)
{
Description = "Push notifikácie z aplikácie PushDemo"
};
var manager = (NotificationManager)GetSystemService(NotificationService)!;
manager.CreateNotificationChannel(channel);
Pri behu si vyžiadajte povolenie cez Permissions.RequestAsync<Permissions.PostNotifications>() z Microsoft.Maui.ApplicationModel. Ak používateľ odmietne, môžete ho neskôr nasmerovať do systémových nastavení cez AppInfo.ShowSettingsUI().
Konfigurácia iOS a APNs s P8 kľúčmi
V Apple Developer Console vytvorte App ID s povolenou capability Push Notifications. Následne v sekcii Keys vygenerujte nový kľúč typu APNs Authentication Key (P8). Stiahnite si .p8 súbor (môžete ho stiahnuť iba raz, takže ho dôkladne zazálohujte). Zapíšte si aj Key ID a Team ID, oba potrebujete vo Firebase Console v sekcii Project Settings → Cloud Messaging → Apple app configuration → APNs Authentication Key.
Apple odporúča P8 namiesto starších p12 certifikátov, pretože nemajú expiráciu, fungujú pre development aj production v jednom kľúči a sú jednoducho rotovateľné. Detaily nájdete v Apple dokumentácii o token-based pripojení k APNs.
Po inicializácii získate FCM token, ktorý jednoznačne identifikuje inštaláciu aplikácie na konkrétnom zariadení. Tento token pošlite na svoj backend a uložte ho v databáze spolu s UserId. Pri každej zmene tokenu (preinštalácia, obnovenie šifrovacieho kľúča) treba záznam aktualizovať.
public class PushTokenService
{
private readonly IFirebaseCloudMessaging _fcm;
private readonly IApiClient _api;
public PushTokenService(IFirebaseCloudMessaging fcm, IApiClient api)
{
_fcm = fcm;
_api = api;
_fcm.TokenChanged += async (s, e) => await RegisterAsync(e.Token);
_fcm.NotificationReceived += OnNotificationReceived;
_fcm.NotificationTapped += OnNotificationTapped;
}
public async Task InitializeAsync()
{
await _fcm.CheckIfValidAsync();
var token = await _fcm.GetTokenAsync();
if (!string.IsNullOrEmpty(token))
await RegisterAsync(token);
}
private Task RegisterAsync(string token) =>
_api.PostAsync("/devices", new { Token = token, Platform = DeviceInfo.Platform.ToString() });
private void OnNotificationReceived(object? sender, FCMNotificationReceivedEventArgs e)
{
// V popredí: zobrazte vlastný in-app banner
Application.Current?.Dispatcher.Dispatch(() =>
Shell.Current.DisplayAlert(e.Notification.Title, e.Notification.Body, "OK"));
}
private async void OnNotificationTapped(object? sender, FCMNotificationTappedEventArgs e)
{
if (e.Notification.Data.TryGetValue("route", out var route))
await Shell.Current.GoToAsync(route!);
}
}
Pre HTTP volania na backend (registrácia tokenu, odhlasovanie z tém) sa hodí slušná servisná vrstva. Vzory pre HttpClient, retry policy a Polly nájdete v článku REST API v .NET MAUI a odolnosť voči chybám.
Spracovanie po zabití aplikácie
Keď je aplikácia úplne zatvorená (kill state) a používateľ klikne na notifikáciu, Android aj iOS spustia aplikáciu so špeciálnym launch intentom. Plugin tieto údaje sprístupní cez FCMNotificationTappedEventArgs.Notification.Data hneď po inicializácii. Preto tap-handler registrujte čo najskôr v lifecycle, ideálne pred prvou navigáciou v App.xaml.cs.
Deep linking z notifikácie do konkrétnej obrazovky
Najčastejší use-case je „klik na notifikáciu → otvoriť detail objednávky #42." Pridajte do FCM payloadu vlastný kľúč route s hodnotou napríklad //orders/detail?id=42. V .NET MAUI Shell zaregistrujte route:
A v OnNotificationTapped handleri (vyššie) zavolajte Shell.Current.GoToAsync(route). Shell automaticky vytvorí ViewModel s parametrom id=42, ak ho označíte atribútom [QueryProperty(nameof(Id), "id")]. Detaily routingu, query parametrov a navigation interceptov rozoberá sprievodca Shell navigáciou v .NET MAUI.
Ako odoslať push notifikáciu z .NET backendu
Na backende v ASP.NET Core použite oficiálny NuGet FirebaseAdmin. Stiahnite si service account JSON kľúč z Firebase Console (Project Settings → Service Accounts) a uložte ho ako secret (Key Vault, environment variable, user secrets pre vývoj). A áno, ten súbor nikdy necommitujte do gitu — videl som projekt, kde takýto kľúč skončil vo verejnom repe a prebral ho bot do 11 hodín.
using FirebaseAdmin;
using FirebaseAdmin.Messaging;
using Google.Apis.Auth.OAuth2;
public class PushSender
{
public PushSender(IConfiguration config)
{
if (FirebaseApp.DefaultInstance is null)
{
FirebaseApp.Create(new AppOptions
{
Credential = GoogleCredential.FromFile(config["Firebase:ServiceAccountPath"])
});
}
}
public async Task<string> SendOrderUpdateAsync(string token, int orderId, string status)
{
var message = new Message
{
Token = token,
Notification = new Notification
{
Title = "Stav objednávky",
Body = $"Objednávka #{orderId} je {status}"
},
Data = new Dictionary<string, string>
{
["route"] = $"//orders/detail?id={orderId}",
["orderId"] = orderId.ToString()
},
Android = new AndroidConfig
{
Priority = Priority.High,
Notification = new AndroidNotification { ChannelId = "default_channel" }
},
Apns = new ApnsConfig
{
Aps = new Aps { Sound = "default", Badge = 1, ContentAvailable = true }
}
};
return await FirebaseMessaging.DefaultInstance.SendAsync(message);
}
}
Pre hromadné odosielanie (newsletter, broadcast) použite SendEachForMulticastAsync s poľom až 500 tokenov. Reálny limit FCM je 600 000 správ za minútu na projekt. Pre väčší objem zvážte batching cez frontu (RabbitMQ, Azure Service Bus) a paralelné worker tasky. Pre autentifikáciu používateľov, ktorí prijímajú notifikácie, sa hodí mať vyriešené tokeny: pozrite si návod na OAuth2 a JWT v .NET MAUI.
Lokálne notifikácie pomocou Plugin.LocalNotification
Nie všetky upozornenia musia ísť cez server. Pripomienka úlohy, ukončenie časovača alebo dosiahnutie cieľa krokov sú scenáre, kde naplánujete notifikáciu priamo z aplikácie. Plugin.LocalNotification 11.x toto rieši pre Android, iOS aj Windows jednotným API.
using Plugin.LocalNotification;
public class ReminderService
{
public async Task ScheduleAsync(string title, string body, DateTime when)
{
if (await LocalNotificationCenter.Current.AreNotificationsEnabled() == false)
await LocalNotificationCenter.Current.RequestNotificationPermission();
var request = new NotificationRequest
{
NotificationId = Random.Shared.Next(1, int.MaxValue),
Title = title,
Description = body,
ReturningData = "task_reminder",
Schedule = new NotificationRequestSchedule
{
NotifyTime = when,
NotifyRepeatInterval = TimeSpan.FromDays(1)
}
};
await LocalNotificationCenter.Current.Show(request);
}
}
Pre dáta pripomienok (úlohy, časy, opakovania) typicky používate lokálnu SQLite databázu. Vzor pre repository a CRUD operácie nájdete v sprievodcovi SQLite v .NET MAUI.
Kedy zvoliť Azure Notification Hubs namiesto FCM
Azure Notification Hubs (ANH) je platený abstraction layer nad FCM, APNs, ADM a WNS. Ak vyvíjate enterprise riešenie alebo potrebujete:
Tag-based segmentáciu, takže pošlete správu všetkým používateľom s tagom region:europe AND plan:premium.
Audit log a compliance (GDPR, HIPAA, ISO 27001) priamo v Azure portáli.
Privátnu sieť cez Private Endpoints a VNet integráciu.
Jeden SDK pre push do Číny cez Baidu Cloud Push.
Kritérium
FCM (Firebase)
Azure Notification Hubs
Cena pre 1M správ/mesiac
Zadarmo
~10 USD (Basic tier)
Maximálny počet zariadení
Bez limitu
100M (Standard tier)
Multi-platformnosť
Android + iOS + Web
Android + iOS + Windows + Amazon
Tag-based broadcast
Cez topics (limit 2000)
Tagy bez limitu, boolean výrazy
SLA
Best effort
99,9 %
Doručovanie do Číny
Nie
Áno (Baidu)
Pre malé a stredne veľké aplikácie je FCM jednoznačne lepšia voľba. ANH dáva zmysel od približne 500 000 zariadení alebo pri špecifických compliance požiadavkách. Microsoft Learn dokumentácia k Azure Notification Hubs obsahuje porovnávacie tabuľky a referenčné architektúry.
Riešenie najčastejších chýb
Chyba „SenderId mismatch" znamená, že google-services.json v aplikácii patrí inému Firebase projektu než service account na backende. Skontrolujte, že obidva sú z toho istého projektu.
iOS notifikácie neprídu v produkcii, ale v debug builde fungujú. Väčšinou je v Entitlements.plist nastavené aps-environment ako development namiesto production. Pri archivácii cez Visual Studio sa Release konfigurácia musí explicitne mapovať na produkčné entitlements. (Toto bol presne ten bug, ktorý ma stál spomínané popoludnie.)
Token sa nezmení po preinštalovaní: Android FCM token je viazaný na inštaláciu aplikácie a po reinstalle dostanete nový. Ak váš backend stále posiela na starý token, dostane UNREGISTERED chybu, ktorú musíte ošetriť a token vymazať z DB.
Notifikácia sa nezobrazí pri zatvorenej aplikácii na Xiaomi/Huawei: niektorí výrobcovia agresívne zabíjajú procesy. Riešenie je požiadať používateľa o vypnutie battery optimization pre vašu aplikáciu cez Settings → Battery → App launch.
Často kladené otázky
Ako otestovať push notifikácie bez backendu?
Najjednoduchšie cez Firebase Console: vľavo Engage → Messaging → Vytvoriť kampaň. Vložte testovací FCM token (získate ho v aplikácii cez await CrossFirebaseCloudMessaging.Current.GetTokenAsync() a logom) a odošlite testovaciu správu. Druhá možnosť je cURL volanie na FCM HTTP v1 API s OAuth2 access tokenom.
Funguje FCM v Číne?
Nie spoľahlivo, pretože Google služby sú v Číne blokované. Pre čínsky trh integrujte natívne SDK ako Xiaomi Push, Huawei HMS Push alebo použite Azure Notification Hubs s Baidu Cloud Push backendom. V .NET MAUI to vyžaduje conditional compilation pre čínsky build flavor.
Aký je rozdiel medzi data-only a notification payloadom?
Notification payload zobrazí systém automaticky a vaša aplikácia ho dostane iba pri tape. Data payload je vždy doručený do kódu, kde si môžete zostaviť vlastnú UI alebo background job. Pre plnú kontrolu (custom UI, silent push) odosielajte iba data a nastavte content_available: true pre iOS.
Áno, Firebase Cloud Messaging je zadarmo bez ohľadu na objem správ aj v produkcii. Platíte iba ak prejdete na Azure Notification Hubs alebo OneSignal Pro. Limity FCM sú technické (4 KB payload, 600k správ/min), nie cenové.
Prečo používateľ nedostane notifikáciu, aj keď je token správny?
Najčastejšie príčiny: chýbajúce POST_NOTIFICATIONS povolenie na Android 13+, nesprávne aps-environment v iOS entitlements, agresívne battery optimization na Xiaomi/Huawei, alebo notification channel s IMPORTANCE_NONE. Skontrolujte v tomto poradí a vždy logujte response z FirebaseMessaging.SendAsync.
Caleb has shipped seven mobile apps to the App Store and Play Store over the last nine years, four of them in Xamarin and three in .NET MAUI. He spent five years at a healthcare-tech company in Boston building a clinician-facing iPad app used by roughly 14,000 nurses, then moved to a freelance practice in 2024 focused on enterprise MAUI rollouts for regulated industries.
His writing tends toward the practical: CI pipelines on App Center successors, MSAL token caching across Android lifecycle resets, MAUI Blazor Hybrid in production, and the awkward seams between MAUI and native SDKs that vendors haven't gotten around to wrapping. He runs a small Discord for enterprise MAUI engineers and writes a Friday newsletter from his home in Portland, Maine.
Praktický sprievodca optimalizáciou .NET MAUI 10: Native AOT, XAML compilation, lov memory leakov, profilovanie pomocou dotnet-trace a checklist pred releasom. S reálnymi metrikami pre iOS aj Android.
Praktický sprievodca implementáciou OAuth2, OpenID Connect a JWT tokenov v .NET MAUI 10. SecureStorage, refresh tokeny, biometria a HTTP message handler v jednej kompletnej príručke.
Naučte sa správne integrovať REST API v .NET MAUI — od HttpClientFactory cez MVVM servisnú vrstvu, platformové handlery, kontrolu pripojenia až po retry a circuit breaker vzory. Praktické príklady pripravené na okamžité použitie.