with one click
shiny-notifications
// Cross-platform local notification management for .NET MAUI apps using Shiny, supporting scheduled, repeating, and geofence-triggered notifications with channels, badges, and interactive actions.
// Cross-platform local notification management for .NET MAUI apps using Shiny, supporting scheduled, repeating, and geofence-triggered notifications with channels, badges, and interactive actions.
Generate code using Shiny.BluetoothLE.Hosting, a BLE peripheral hosting library for .NET with GATT server, advertising, and managed characteristic patterns
Shiny BluetoothLE client/central operations for scanning, connecting, and communicating with BLE peripherals
Background job scheduling and execution for .NET MAUI (iOS/Android native OS schedulers) and in-process jobs for plain .NET, Linux, macOS, and Blazor WASM using Shiny.Jobs
Guide for generating code that uses Shiny.NET HTTP Transfers for background uploads and downloads on iOS/Android, Windows, Linux, macOS, and Blazor WASM (Service Worker Background Sync)
GPS tracking, geofence monitoring, and motion activity recognition for .NET MAUI, iOS, and Android using Shiny.Locations
Core infrastructure, hosting, DI, key-value stores, lifecycle hooks, and platform abstractions for Shiny on .NET MAUI, iOS, and Android
| name | shiny-notifications |
| description | Cross-platform local notification management for .NET MAUI apps using Shiny, supporting scheduled, repeating, and geofence-triggered notifications with channels, badges, and interactive actions. |
| auto_invoke | true |
| triggers | ["local notifications","notification manager","notification channel","notification delegate","push notification","scheduled notification","geofence notification","repeating notification","badge count","notification actions","Shiny.Notifications","INotificationManager","INotificationDelegate","notification permission","notification sound","channel importance"] |
Use this skill when the user needs to:
| Item | Value |
|---|---|
| NuGet Package | Shiny.Notifications (iOS, Mac Catalyst, Android, macOS, Windows); Shiny.Notifications.Linux (Linux) |
| Primary Namespace | Shiny.Notifications |
| Registration Namespace | Shiny (extension methods on IServiceCollection) |
| Platforms | iOS, Mac Catalyst, Android, macOS, Windows, Linux |
| Dependencies | Shiny.Core, Shiny.Locations, Shiny.Support.Repositories |
Linux notifications ship in a separate package, Shiny.Notifications.Linux. They are delivered via the freedesktop org.freedesktop.Notifications D-Bus service (GNOME, KDE, XFCE, etc.) and support the same INotificationManager API surface as the other platforms. Scheduled notifications are tracked in-process only — there is no OS-level scheduler like BGTaskScheduler or WorkManager, so the host process must be running for a scheduled notification to fire. Channels are exposed but only a subset of freedesktop hints (urgency, category, image) are actually honoured by most daemons. Geofence triggers and time-sensitive flags are not applicable.
Register with services.AddNotifications<TDelegate>(); from the Shiny namespace — the same call site as the other platforms.
Register the notification services in your MauiProgram.cs:
using Shiny;
// Without a delegate (fire-and-forget notifications)
services.AddNotifications();
// With a delegate to handle notification taps
services.AddNotifications<MyNotificationDelegate>();
On iOS, you can optionally pass an IosConfiguration to control authorization and presentation options:
#if IOS || MACCATALYST
services.AddNotifications<MyNotificationDelegate>(new IosConfiguration(
UNAuthorizationOptions: UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound,
PresentationOptions: UNNotificationPresentationOptions.Banner | UNNotificationPresentationOptions.Badge | UNNotificationPresentationOptions.Sound
));
#endif
When generating code that uses Shiny Notifications, follow these conventions:
Always request access before sending notifications:
var access = await notificationManager.RequestAccess();
if (access != AccessState.Available)
{
// Handle denied permission
return;
}
Use AccessRequestFlags when the notification uses triggers:
AccessRequestFlags.TimeSensitivity for scheduled or repeating notifications.AccessRequestFlags.LocationAware for geofence-triggered notifications.RequestRequiredAccess extension method that infers flags from the notification object.A Notification must have a Message set -- validation will throw otherwise.
Only one trigger type per notification -- you cannot mix ScheduleDate, RepeatInterval, and Geofence on the same notification.
Implement INotificationDelegate for handling user taps:
public class MyNotificationDelegate : INotificationDelegate
{
public async Task OnEntry(NotificationResponse response)
{
// response.Notification -- the original notification
// response.ActionIdentifier -- which action button was pressed
// response.Text -- text reply if action was TextReply type
}
}
Create channels before sending notifications that reference them:
notificationManager.AddChannel(new Channel
{
Identifier = "alerts",
Importance = ChannelImportance.High,
Sound = ChannelSound.High
});
Use the convenience Send extension for simple notifications:
await notificationManager.Send("Title", "Message body");
For platform-specific properties, use the native subclasses:
AndroidNotification and AndroidChannelAppleNotification and AppleChannelAlways inject INotificationManager via constructor injection -- never create instances directly.
Use CancelScope wisely when cancelling:
CancelScope.DisplayedOnly -- clears only shown notifications.CancelScope.Pending -- clears only scheduled/triggered notifications.CancelScope.All -- clears everything (default).Notification: Both Shiny.Notifications and Shiny.Push define a Notification type. If both packages are referenced in the same project, do NOT add both namespaces as global usings. Use Shiny.Notifications.Notification FQN or a file-level using Shiny.Notifications; directive to disambiguate.AccessState result before attempting to send notifications.Channel.Default) always exists with Identifier = "Notifications" and ChannelImportance.Low.InvalidOperationException.BadgeCount only on immediate notifications (not triggered ones) -- validation will fail otherwise.IntervalTrigger with either Interval (raw TimeSpan) or TimeOfDay (daily/weekly recurring), never both.Center and Radius are both set on GeofenceTrigger.notification for the default small icon, or set SmallIconResourceName on AndroidNotification.RequestRequiredAccess extension method to automatically determine needed permission flags from a Notification object.Payload dictionary on Notification to pass custom data that you can read back in your INotificationDelegate.OnEntry.