maui-local-notifications
Installation
SKILL.md
.NET MAUI Local Notifications
Implementation overview
- Define cross-platform
INotificationManagerServiceinterface and event args - Implement Android notification service (channel, AlarmManager, BroadcastReceiver)
- Implement iOS/Mac Catalyst notification service (UNUserNotificationCenter)
- Register platform implementations via DI
- Configure platform permissions and MainActivity
See references/local-notifications-api.md for full implementation code.
Platform gotchas
Android
| Issue | Fix |
|---|---|
| Notifications silently fail on API 33+ | Must request POST_NOTIFICATIONS runtime permission first |
PendingIntent crash on Android 12+ |
Must include PendingIntentFlags.Immutable for API 31+ |
| Scheduled notifications lost on reboot | AlarmManager does not survive device restart — re-schedule on boot via BOOT_COMPLETED receiver |
| No notification appears | Channel not created — required on API 26+ (Android 8.0) |
| Notification tap doesn't return to app | LaunchMode = LaunchMode.SingleTop must be set on MainActivity |
// ✅ Correct — API 31+ requires Immutable flag
var pendingIntentFlags = (Build.VERSION.SdkInt >= BuildVersionCodes.S)
? PendingIntentFlags.CancelCurrent | PendingIntentFlags.Immutable
: PendingIntentFlags.CancelCurrent;
// ❌ Wrong — crashes on Android 12+
var pendingIntentFlags = PendingIntentFlags.CancelCurrent;
iOS / Mac Catalyst
| Issue | Fix |
|---|---|
| No notification prompt appears | Permission already denied — user must re-enable in Settings |
| Foreground notifications don't show | Must implement UNUserNotificationCenterDelegate and set Current.Delegate |
Notification shows Alert not Banner |
Use UNNotificationPresentationOptions.Banner on iOS 14+ |
// ✅ iOS 14+ — use Banner
completionHandler(OperatingSystem.IsIOSVersionAtLeast(14)
? UNNotificationPresentationOptions.Banner
: UNNotificationPresentationOptions.Alert);
// ❌ Always using Alert — deprecated on iOS 14+
completionHandler(UNNotificationPresentationOptions.Alert);
Windows
⚠️ Windows App SDK supports toast notifications but scheduled notifications are not yet supported. Immediate notifications work.
DI registration — platform-specific only
// ✅ Must use #if guards — there's no cross-platform implementation
#if ANDROID
builder.Services.AddTransient<INotificationManagerService,
Platforms.Android.NotificationManagerService>();
#elif IOS
builder.Services.AddTransient<INotificationManagerService,
Platforms.iOS.NotificationManagerService>();
#elif MACCATALYST
builder.Services.AddTransient<INotificationManagerService,
Platforms.MacCatalyst.NotificationManagerService>();
#endif
Common anti-patterns
// ❌ Sending without checking permission — silent failure on API 33+
notificationManager.SendNotification("Title", "Body");
// ✅ Request permission first
#if ANDROID
var status = await Permissions.RequestAsync<Platforms.Android.NotificationPermission>();
if (status != PermissionStatus.Granted) return;
#endif
// ❌ Updating UI directly from notification callback — cross-thread exception
notificationManager.NotificationReceived += (s, e) =>
myLabel.Text = ((NotificationEventArgs)e).Title;
// ✅ Marshal to UI thread
notificationManager.NotificationReceived += (s, e) =>
MainThread.BeginInvokeOnMainThread(() =>
myLabel.Text = ((NotificationEventArgs)e).Title);
Decision framework
| Need | Approach |
|---|---|
| Immediate notification | SendNotification(title, message) with null notifyTime |
| Scheduled reminder | SendNotification(title, message, DateTime.Now.AddMinutes(30)) |
| Persist across reboot (Android) | Add BOOT_COMPLETED receiver to re-schedule alarms |
| Rich notifications (images, actions) | Extend platform implementations with native APIs |
| Push notifications from server | Use a different pattern entirely (FCM/APNs) |
Quick checklist
- Cross-platform
INotificationManagerServiceinterface defined - Android: notification channel created (API 26+)
- Android:
POST_NOTIFICATIONSpermission in manifest + runtime request (API 33+) - Android:
PendingIntentFlags.Immutableused (API 31+) - Android:
MainActivityhasLaunchMode.SingleTopand handlesOnNewIntent - iOS:
UNUserNotificationCenterDelegateset for foreground display - iOS:
Bannerused instead ofAlerton iOS 14+ - DI registration uses
#ifplatform guards - UI updates from notification callbacks use
MainThread.BeginInvokeOnMainThread
Related skills