mcpField
M
maui-local-notifications

maui-local-notifications

github.com/davidortinau开发17651 次安装16 周前更新
代码仓库

关于 maui-local-notifications

.NET MAUI 本地通知实现指南,面向需要跨平台发送或安排通知的开发者。它汇总 Android、iOS、Mac Catalyst 与 Windows 的实现要点和平台限制。

主要功能

  1. 01跨平台通知服务设计
  2. 02Android 通知权限与渠道配置
  3. 03Android 重启后重新安排通知
  4. 04iOS 与 Mac Catalyst 前台通知处理
  5. 05Windows 定时通知限制

适用场景

  1. 01实现即时本地通知
  2. 02安排提醒并处理 Android 重启
  3. 03排查通知权限或前台显示问题
  4. 04根据平台能力规划通知功能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/davidortinau/maui-skills --skill maui-local-notifications

安装后在 Claude Code 中输入/maui-local-notifications确认已加载。

附带文件references/local-notifications-api.md

详细介绍

.NET MAUI 本地通知

实现概述

  1. 定义跨平台的 INotificationManagerService 接口和事件参数
  2. 实现 Android 通知服务(通道、AlarmManager、BroadcastReceiver)
  3. 实现 iOS/Mac Catalyst 通知服务(UNUserNotificationCenter)
  4. 通过 DI 注册平台实现
  5. 配置平台权限和 MainActivity

完整实现代码请参见 references/local-notifications-api.md。

平台注意事项

Android
问题解决方法
API 33+ 上通知静默失败必须先请求 POST_NOTIFICATIONS 运行时权限
Android 12+ 上 PendingIntent 崩溃API 31+ 必须包含 PendingIntentFlags.Immutable
设备重启后计划通知丢失AlarmManager 无法在设备重启后保留 — 通过 BOOT_COMPLETED 接收器在启动时重新安排
未显示通知未创建通道 — API 26+(Android 8.0)必需
点击通知后未返回应用必须在 MainActivity 上设置 LaunchMode = LaunchMode.SingleTop
// ✅ 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
问题解决方法
未显示通知提示权限已被拒绝 — 用户必须在“设置”中重新启用
前台通知未显示必须实现 UNUserNotificationCenterDelegate 并设置 Current.Delegate
通知显示为 Alert 而非 Banner在 iOS 14+ 上使用 UNNotificationPresentationOptions.Banner
// ✅ 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 支持 toast 通知,但尚不支持计划通知。即时通知可正常使用。

DI 注册 — 仅平台特定实现

// ✅ 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

常见反模式

// ❌ 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);

决策框架

需求方案
即时通知使用 null notifyTime 调用 SendNotification(title, message)
计划提醒调用 SendNotification(title, message, DateTime.Now.AddMinutes(30))
重启后保留(Android)添加 BOOT_COMPLETED 接收器以重新安排闹钟
丰富通知(图片、操作)使用原生 API 扩展平台实现
来自服务端的推送通知使用完全不同的模式(FCM/APNs)

快速检查清单

  • 已定义跨平台的 INotificationManagerService 接口
  • Android:已创建通知通道(API 26+)
  • Android:清单中包含 POST_NOTIFICATIONS 权限,并请求运行时权限(API 33+)
  • Android:已使用 PendingIntentFlags.Immutable(API 31+)
  • Android:MainActivity 设置了 LaunchMode.SingleTop,并处理 OnNewIntent
  • iOS:已设置 UNUserNotificationCenterDelegate 以显示前台通知
  • iOS:在 iOS 14+ 上使用 Banner 而非 Alert
  • DI 注册使用 #if 平台保护
  • 通知回调触发的 UI 更新使用 MainThread.BeginInvokeOnMainThread

评论

支持 Markdown