关于 maui-push-notifications
这项 .NET MAUI 技能介绍 Android 和 iOS 推送通知的实现与故障排查,提供平台检查清单,并说明令牌注册、权限、通知渠道及 Azure Notification Hub 的限制。
主要功能
- 01说明令牌刷新与重新注册
- 02涵盖 Android 通知权限和渠道
- 03列出 iOS APNs 配置要求
- 04说明平台注册值
- 05介绍 Azure Notification Hub 标签限制
- 06提供 Android、iOS 和后端检查清单
适用场景
- 01排查 Android 通知未送达
- 02调试令牌注册与刷新问题
- 03为实体设备准备 iOS 推送配置
- 04避免 Azure Notification Hub 标签限制错误
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ davidortinau/ maui-skills --skill maui-push-notifications安装后在 Claude Code 中输入/maui-push-notifications确认已加载。
附带文件references/push-notifications-api.md
详细介绍
推送通知 — 注意事项与最佳实践
故障排查表
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 每次调试运行时令牌都会变化(Android) | 调试构建会重新生成 Firebase 令牌 | 始终在 OnNewToken 中重新注册 |
HttpClient 请求静默失败 | BaseAddress 末尾缺少 / | 确保端点以 / 结尾 |
| iOS 推送无法送达模拟器 | 模拟器不支持 APNS | 使用实体 iOS 设备 |
| Android 13+ 上没有通知 | 需要 POST_NOTIFICATIONS(API 33+) | 在 OnCreate 中调用 RequestPermissions |
| 缺少通知渠道(API 26+) | Android 要求显式创建渠道 | 发送前创建渠道 |
SendNotificationAsync 因标签超过 20 个而抛出异常 | Azure NH 标签表达式限制 | 将标签分成每组 20 个进行批处理 |
设备注册时出现 422 | 平台字符串不匹配 | 使用 "fcmv1"(而非 "gcm")和 "apns" |
RegisterAsync 时令牌为空 | 冷启动时发生竞态条件 | 使用 IsNullOrWhiteSpace 检查进行保护 |
关键注意事项
⚠️ BaseAddress 末尾必须有斜杠
HttpClient.BaseAddress 必须以 / 结尾。否则,相对 URI 解析会静默失效。
// ❌ Relative URIs resolve incorrectly
_http = new HttpClient { BaseAddress = new Uri("https://example.com") };
// ✅ Trailing slash required
_http = new HttpClient { BaseAddress = new Uri("https://example.com/") };
⚠️ Android:令牌刷新时始终重新注册
Firebase 令牌在调试构建中会频繁重新生成。如果跳过 OnNewToken,后端就会保留过期令牌,导致推送静默失败。
// ❌ Only registering once at startup
// (token may change later without re-registration)
// ✅ Always re-register in OnNewToken
public override void OnNewToken(string token)
{
var svc = IPlatformApplication.Current?.Services.GetService<IPushNotificationService>();
if (svc is null) return;
svc.Token = token;
_ = svc.RegisterAsync();
}
⚠️ Android 13+ 需要 POST_NOTIFICATIONS 权限
在 API 33+ 上,如果不显式请求 POST_NOTIFICATIONS,通知会被静默丢弃。
⚠️ Azure NH 标签表达式限制:20 个标签
如果标签表达式引用的标签超过 20 个,SendNotificationAsync 就会抛出异常。请分批处理:
// ✅ Batch tags to stay under the limit
var batches = request.Tags.Chunk(20);
foreach (var batch in batches)
{
var tagExpr = string.Join(" || ", batch);
await _hub.SendFcmV1NativeNotificationAsync(payload, tagExpr, ct);
}
⚠️ 使用 "fcmv1",而非 "gcm"
旧版 "gcm" 平台字符串会导致设备注册时出现 422 错误。Android 始终使用 "fcmv1",iOS 使用 "apns"。
⚠️ iOS 模拟器无法接收推送通知
APNS 仅适用于实体 iOS 设备。模拟器会静默忽略推送注册。
平台检查清单
Android
- 将
google-services.json放在Platforms/Android/中,并在.csproj中配置<GoogleServicesJson> - 添加
Xamarin.Firebase.MessagingNuGet 包(仅限 Android 的条件) - 在 API 33+ 上请求
POST_NOTIFICATIONS权限 - 在发送首条通知前创建通知渠道(API 26+)
-
OnNewToken始终调用RegisterAsync - 在清单中注册
FirebaseMessagingService,并配置MESSAGING_EVENTintent 过滤器
iOS
- 在 Apple Developer 门户中启用 Push Notifications 功能
- 将 APNs 密钥(
.p8)上传到 Azure Notification Hub - 配置
Entitlements.plist,将aps-environment设为development或production - 在
.csproj中设置CodesignEntitlements - 获得授权后,在主线程上调用
RegisterForRemoteNotifications - 将设备令牌转换为小写十六进制字符串(不含连字符)
后端
- 使用 FCM V1 JSON 和 APNS 密钥配置 Azure Notification Hub
-
BaseAddress以/结尾 - 将标签表达式分成每组 ≤20 个进行批处理
- 平台字符串:
"fcmv1"和"apns"(不是旧版值)
架构概览
MAUI app → ASP.NET Core backend → Azure Notification Hub → FCM / APNS → device
完整实现模板请参阅 references/push-notifications-api.md。
评论
支持 Markdown