
Skill
maui-notifications-deep-links
implement MAUI notifications and deep links
Description
Implement .NET MAUI local notifications, push notifications, Firebase/FCM legacy server-key migration to FCM HTTP v1, APNs/Azure Notification Hubs registration, app links, universal links, custom URI schemes, token refresh/sign-in/logout lifecycle, push payload safety, and deep-link troubleshooting. USE FOR: notification permission UX, Android NotificationChannel and POST_NOTIFICATIONS, iOS UNUserNotificationCenter, push token upload, notification tap navigation, assetlinks.json autoVerify, apple-app-site-association, and CFBundleURLTypes. DO NOT USE FOR: OAuth callback-only flows, generic Shell navigation, or picker/location permissions.
SKILL.md
MAUI Notifications and Deep Links
Use this skill when a MAUI app needs scheduled local alerts, remote push notifications, or URLs that open the app and navigate to content.
Workflow
- Separate the entry points: local notification scheduling, push token registration, notification tap handling, custom URI schemes, and verified web links.
- Add platform declarations and entitlements before writing app logic.
- Request notification permission at a useful moment and support a denied state.
- For migrated push-token guidance, explicitly say Android backends use the official FCM HTTP v1 / Firebase Cloud Messaging v1 API with service-account OAuth credentials, not legacy server keys. Treat OAuth 2.0 as the credential flow, not the API version. iOS uses APNs device tokens.
- Register refreshed device push tokens/installations with the backend or Azure Notification Hubs after sign-in, and disassociate them on logout.
- Treat Azure Notification Hubs as optional infrastructure unless the app needs brokered installations, tags, templates, or multi-platform fanout.
- Keep push payloads free of PII, access tokens, and confidential content; send route/entity IDs and fetch sensitive data after the app opens.
- Normalize all notification taps and deep links into one app navigation service.
- Route links with Shell routes or an explicit navigation abstraction.
- Add diagnostics for token registration, payload parsing, and cold-start versus resume handling.
Local Notifications
.NET MAUI apps typically implement local notifications with platform services or a vetted toolkit abstraction.
public interface INotificationService
{
Task RequestPermissionAsync(CancellationToken cancellationToken);
Task ScheduleReminderAsync(string id, string title, string body, DateTimeOffset when);
Task CancelAsync(string id);
}
| Platform | Required considerations |
|---|---|
| Android | Create a NotificationChannel for Android 8+, request POST_NOTIFICATIONS on Android 13+, and include stable channel IDs. |
| iOS/Mac Catalyst | Request notification authorization through UserNotifications and handle foreground presentation explicitly. |
| Windows | Use the Windows app notification APIs appropriate for the packaged target. |
Keep notification IDs stable when updates/cancellation are required. Store scheduled notification metadata in app storage if it must survive app restart. If notification permission is denied, surface an in-app reminders state, banner, or inbox fallback and provide a Settings path instead of silently dropping the schedule request.
Push Notifications
When the prompt mentions migrating a legacy Firebase server key, legacy FCM API, or Xamarin push registrations, include these required points:
- Android senders move to the official FCM HTTP v1 / Firebase Cloud Messaging v1 API with service-account OAuth credentials. Do not recommend legacy server keys. Treat OAuth 2.0 service-account authentication as the credential flow, not the API version.
- iOS uses APNs device tokens, with sandbox/production environment alignment.
- Azure Notification Hubs is optional infrastructure, not required for direct FCM/APNs token registration.
- Upload refreshed tokens/installations after sign-in, associate them with the authenticated user, and disassociate or unregister them on logout.
- Keep push payloads free of PII, access tokens, and confidential data; send route/entity IDs and fetch sensitive content after the app opens.
- Android uses Firebase Cloud Messaging (FCM); use the official FCM HTTP v1 API on the backend. The legacy FCM HTTP API was retired in June 2024 and should not be used for migrated Xamarin or new MAUI apps.
- iOS and Mac Catalyst use APNs.
- Windows packaged apps use Windows Notification Service (WNS) channel URIs.
- Small apps can register FCM/APNs/WNS tokens directly with their own backend. Azure Notification Hubs is optional and useful when the app needs a broker for tags, installations, or multi-platform push management.
- When using Azure Notification Hubs with FCM, configure FCM HTTP v1 service-account credentials rather than legacy server keys.
- Migrating the backend send API from legacy FCM to FCM HTTP v1 does not require a new client registration-token format; keep normal token refresh handling because FCM can still rotate tokens.
- Upload the current push token/installation ID to the backend after it changes.
- Protect token registration endpoints with app user authentication. Associate tokens with the signed-in user only after auth completes, and remove or disassociate them on logout.
- Do not put secrets, access tokens, or sensitive content in push payloads.
- Include a stable route or entity ID in the payload, then fetch sensitive data after the app opens.
Deep Link Patterns
| Link type | Use when | Platform setup |
|---|---|---|
| Custom URI scheme | App-private callbacks or simple app opens such as myapp://orders/42 | Android intent filter, iOS/Mac Catalyst CFBundleURLTypes, Windows protocol registration |
| Android App Links | Verified HTTPS links on Android | Intent filter with autoVerify and hosted assetlinks.json |
| iOS Universal Links | Verified HTTPS links on iOS/Mac Catalyst | Associated Domains entitlement and hosted apple-app-site-association |
Use one parser that accepts all launch sources:
- App launched cold from a URL.
- App resumed from background by a URL.
- User tapped a local notification.
- User tapped a push notification.
Wiring Deep Link Interception
Route native launch callbacks into one link handler:
builder.ConfigureLifecycleEvents(events =>
{
events.AddAndroid(android =>
{
android.OnCreate((activity, _) =>
{
var uri = activity.Intent?.Data?.ToString();
if (!string.IsNullOrEmpty(uri))
DeepLinkRouter.Route(uri);
});
android.OnNewIntent((activity, intent) =>
{
var uri = intent?.Data?.ToString();
if (!string.IsNullOrEmpty(uri))
DeepLinkRouter.Route(uri);
});
});
events.AddiOS(ios => ios.OpenUrl((app, url, options) =>
{
DeepLinkRouter.Route(url.AbsoluteString);
return true;
}));
});
Override App.OnAppLinkRequestReceived(Uri uri) for verified HTTPS app links
and universal links, then forward the URI to the same parser used by
notifications and custom schemes.
For cold-start links or notification taps, queue the route until MAUI has built
the app navigation surface. Do not call Shell.Current.GoToAsync from Android
OnCreate before Shell.Current exists.
While a queued link is resolving, show a pending navigation/loading state; after
arrival, move focus to the destination heading or announce the destination with
SemanticScreenReader.Announce.
Troubleshooting Checklist
- Confirm the app package ID/bundle ID matches the FCM/APNs/Azure registration.
- Confirm APNs sandbox versus production environment matches the build.
- Confirm Android notification channel IDs are created before posting.
- Confirm Android 13+ notification runtime permission is granted.
- Confirm app link/universal link association files are reachable without redirects that break platform verification.
- Confirm link payloads map to registered Shell routes or navigation commands.
Validation Checklist
- Notification permissions and platform declarations are present and scoped.
- Push migration guidance names FCM HTTP v1/service-account credentials, APNs, and Notification Hubs as optional infrastructure.
- Push tokens are uploaded, refreshed, and disassociated on logout.
- Notification payloads contain route/entity references, not PII, access tokens, or secrets.
- Deep links work for cold start and resume.
- Cold-start links expose a pending state and announce/focus the destination when routing completes.
- App link/universal link verification files match the app identifiers.
More skills from the maui-labs repository
View all 32 skillsandroid-slim-bindings
create Android slim bindings for .NET
Jul 12.NETAndroidJavaKotlin +1devflow-automation
automate .NET MAUI app state
Jul 12.NETAutomationMAUIMobiledevflow-connect
diagnose DevFlow agent connectivity issues
Jul 12DebuggingMAUINetworkingdotnet-workload-info
discover MAUI workload metadata
Jul 12C#CLIEngineeringMAUIios-slim-bindings
create iOS slim bindings for MAUI
Jul 12.NETiOSMAUISwift +1maui-accessibility
implement accessibility in .NET MAUI apps
Jul 12.NETAccessibilityMAUIMobile +1
More from .NET (Microsoft)
View publishermultithreaded-task-migration
migrate MSBuild tasks to multithreaded mode
msbuild
Jul 12.NETEngineeringPerformanceanalyzing-dotnet-performance
analyze .NET code for performance anti-patterns
skills
Jul 12.NETCode AnalysisDebuggingPerformanceandroid-tombstone-symbolication
symbolicate .NET runtime frames in Android tombstones
skills
Jul 12.NETAndroidDebuggingMicrosoftapple-crash-symbolication
symbolicate .NET runtime frames in crash logs
skills
Jul 12.NETDebuggingiOSmacOS +1assertion-quality
evaluate assertion quality in test suites
skills
Jul 12Code AnalysisQATestingauthor-component
create and review Blazor components
skills
Jul 15.NETBlazorC#UI Components +1