关于 push-notification-best-practices
为移动应用开发者提供推送通知实施与排错指南,涵盖 iOS、Android、React Native、Expo 和 Flutter。内容按平台整理配置、令牌、消息处理及深层链接规则,并提供问题到规则的索引。
主要功能
- 01覆盖五类移动平台
- 02提供平台专属配置清单
- 03说明令牌注册与刷新
- 04比较消息负载与后台处理
- 05提供深层链接排错规则
适用场景
- 01为移动应用配置推送通知
- 02排查通知未送达或未显示
- 03实现后台消息处理
- 04检查令牌管理和深层链接
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ clix-so/ skills --skill push-notification-best-practices安装后在 Claude Code 中输入/push-notification-best-practices确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdLICENSE.txtmetadata.jsonrules/_sections.mdandroid-google-services.mdandroid-messaging-service.mdandroid-notification-channel.mdandroid-notification-icon.mdandroid-permission.mdandroid-priority-high.mddeeplink-navigation-conflict.mddeeplink-terminated-state.mdinfra-backup-fid.mdinfra-firewall-ports.mdinfra-rate-limiting.mdios-apns-auth-key.mdios-delegate-setup.mdios-extension-build.mdios-foreground-display.mdios-method-swizzling.mdios-permission-request.mdios-token-registration.mdmessage-background-handler.mdmessage-data-vs-notification.mdmessage-foreground-handler.mdpermission-timing.mdtesting-debugging.mdtoken-invalidation.mdtoken-refresh.mdtoken-registration.md详细介绍
推送通知最佳实践
概览
移动应用中推送通知的实现与故障排除综合指南。涵盖 iOS(APNS)、Android(FCM)、React Native、Expo 和 Flutter 平台,包括平台特定的配置、令牌管理、消息处理和深层链接模式。
平台支持矩阵
| 平台 | 离线推送 | 通知栏 | 点击导航 | 应用内提示 | 后台处理器 |
|---|---|---|---|---|---|
| iOS | APNS | 系统 | 深层链接 | 自定义 | 仅包含 data 的载荷 |
| Android | FCM | 系统 | Intent | 自定义 | 仅包含 data 的载荷 |
| React Native | APNS/FCM | 系统 | React Navigation | 自定义 | setBackgroundMessageHandler |
| Expo | Expo Push | 系统 | Linking | 自定义 | TaskManager |
| Flutter | APNS/FCM | 系统 | Navigator | 自定义 | onBackgroundMessage |
决策树
何时请求权限
何时请求通知权限?
User installing app
|
v
[First launch?] ──Yes──> [Show value proposition first]
| |
No v
| [User action triggers need?]
v |
[Already granted?] Yes
| |
Yes v
| [Request permission] ──> 70-80% acceptance rate
v
[Notifications ready]
| 时机 | 接受率 | 使用场景 |
|---|---|---|
| 立即(应用启动时) | 15-20% | 低活跃度应用 |
| 完成引导后 | 40-50% | 标准应用 |
| 用户主动操作时 | 70-80% | 高活跃度应用 |
建议: 先说明通知的价值,或在用户启用相关功能时再请求权限。
静默通知与可见通知
我应该使用哪种载荷类型?
[What's the purpose?]
|
+──> Time-sensitive user alert ──> Visible (notification payload)
|
+──> Background data sync ──> Silent (data-only payload)
|
+──> Custom UI required ──> Silent (data-only payload)
|
+──> Need background processing ──> Silent (data-only payload)
| 场景 | 载荷类型 | 原因 |
|---|---|---|
| 新消息提醒 | 可见 | 用户需要立即关注 |
| 订单状态更新 | 可见 | 信息具有时效性 |
| 后台同步 | 静默 | 无需打扰用户 |
| 自定义通知 UI | 静默 | 可完全控制显示方式 |
| 更新角标数量 | 静默 | 需要在后台处理 |
扩展策略(iOS)
何时使用 Notification Service Extension?
- 需要在显示通知前修改通知内容
- 需要下载并附加媒体(图片、视频)
- 需要解密端到端加密的载荷
- 需要动态添加操作按钮
何时使用 Notification Content Extension?
- 需要超出系统模板的自定义通知 UI
- 需要在展开视图中加入交互元素
反模式(绝对不要这样做)
权限处理
| 绝对不要 | 原因 | 应采取的做法 |
|---|---|---|
| 首次启动时不作说明就请求权限 | 接受率只有 15-20% | 先说明价值,再请求权限 |
| 用户拒绝后再次请求 | 系统会忽略重复请求 | 显示前往设置的引导 |
| 忽略临时授权 | 会错过 iOS 12+ 的静默送达 | 使用 .provisional 选项 |
令牌管理
| 绝对不要 | 原因 | 应采取的做法 |
|---|---|---|
| 长期缓存令牌 | 重新安装或恢复后令牌可能变化 | 始终使用回调返回的最新令牌 |
| 假设令牌格式固定 | 格式因平台/SDK 而异 | 将其视为不透明字符串 |
| 发送令牌时不关联用户 | 无法指定通知目标 | 在后端将其与 userId 关联 |
| 存储令牌时不记录设备 ID | 同一用户可能产生重复令牌 | 使用 deviceId 作为唯一键 |
消息处理
| 绝对不要 | 原因 | 应采取的做法 |
|---|---|---|
使用 notification 载荷进行后台处理 | 后台运行时不会调用 onMessageReceived | 使用仅包含 data 的载荷 |
| 依赖静默通知实现有时效要求的送达 | 无法保证送达 | 使用可见通知 |
| 在后台处理器中执行耗时操作 | 系统会在约 30 秒后终止应用 | 将工作加入队列并快速处理 |
| 忘记处理两种载荷类型 | 会遗漏通知 | 同时处理 notification 和 data 载荷 |
iOS 特定规则
| 绝不 | 原因 | 应采用的做法 |
|---|---|---|
| 在设置代理之前注册通知 | 不会调用代理方法 | 在 registerForRemoteNotifications() 之前设置代理 |
不实现 serviceExtensionTimeWillExpire() | 内容修改会失败 | 始终实现回退方案 |
| 使用 .p12 证书 | 每年过期,且已弃用 | 使用 .p8 身份验证密钥 |
Android 特定规则
| 绝不 | 原因 | 应采用的做法 |
|---|---|---|
| 不创建 NotificationChannel | Android 8.0+ 上不会显示通知 | 在应用启动时创建渠道 |
后台处理程序使用 normal 优先级 | 休眠模式会阻止消息送达 | 使用 high 优先级 |
| 使用彩色通知图标 | Android 会忽略颜色,并显示白色方块 | 使用白色透明背景图标 |
技能格式
每个规则文件都采用混合格式,兼顾快速查找和深入理解:
- 快速模式:提供错误/正确的代码片段,便于立即匹配模式
- 适用场景:说明此规则适用的情况
- 深入解析:提供完整背景信息,包括分步指南和平台特定细节
- 常见陷阱:列出常见错误及避免方法
- 相关规则:交叉引用相关模式
影响评级:CRITICAL(立即修复)、HIGH(显著改进)、MEDIUM(值得优化)
适用场景
在以下情况下参考这些指南:
- 在移动应用中设置推送通知
- 调试推送通知送达问题
- 实现后台通知处理程序
- 将深层链接与推送通知集成
- 管理推送令牌和设备注册
- 排查平台特定的推送问题
- 审查推送通知代码的可靠性
按优先级排序的指南
| 优先级 | 类别 | 影响 | 前缀 |
|---|---|---|---|
| 1 | iOS 设置 | CRITICAL | ios- |
| 2 | Android 设置 | CRITICAL | android- |
| 3 | 令牌管理 | HIGH | token- |
| 4 | 消息处理 | HIGH | message- |
| 5 | 深层链接 | MEDIUM | deeplink- |
| 6 | 基础设施 | MEDIUM | infra- |
快速参考
关键:iOS 设置
设置清单:
- 从 Apple Developer 生成 APNs 身份验证密钥(.p8)
- 在 Firebase Console 中上传密钥,并填写 Key ID 和 Team ID
- 在 Xcode 中启用 Push Notifications 功能
- 在 didFinishLaunchingWithOptions 中设置 UNUserNotificationCenter 代理
- 在注册之前请求通知授权
- 实现前台展示选项
关键:Android 设置
设置清单:
- 将 google-services.json 添加到 app/ 目录
- 应用 google-services Gradle 插件
- 创建 NotificationChannel(Android 8.0+)
- 请求 POST_NOTIFICATIONS 权限(Android 13+)
- 实现 FirebaseMessagingService
- 设置通知图标(透明背景 + 白色)
- 使用 'high' 优先级以兼容休眠模式
高优先级:令牌管理
令牌生命周期:
// 1. Register token with server
const token = await getToken();
await registerToken(token, userId);
// 2. Handle token refresh
onTokenRefresh((newToken) => {
updateTokenOnServer(newToken, userId);
});
// 3. Handle invalidation
if (error.code === 'DeviceNotRegistered') {
deleteTokenFromDatabase(token);
}
高优先级:消息处理
载荷类型:
- 仅 data:后台处理程序会在两个平台上运行
- notification + data:iOS/Android 的行为有所不同
- iOS:始终显示通知
- Android:后台 = 系统托盘,前台 = onMessageReceived
优先级设置:
- 对时效性要求高的通知使用
priority: 'high' - Android 休眠模式后台处理程序必须使用此设置
规则
完整文档和代码示例见 rules/:
iOS 设置(ios-*)
| 文件 | 影响 | 描述 |
|---|---|---|
ios-apns-auth-key.md | CRITICAL | APNs 身份验证密钥设置 |
ios-delegate-setup.md | CRITICAL | UNUserNotificationCenter 委托配置 |
ios-permission-request.md | CRITICAL | 通知权限请求流程 |
ios-token-registration.md | HIGH | APNS 令牌注册与处理 |
ios-foreground-display.md | HIGH | 在前台显示通知 |
ios-method-swizzling.md | MEDIUM | 方法替换管理 |
ios-extension-build.md | MEDIUM | 通知服务扩展设置 |
Android 设置(android-*)
| 文件 | 影响 | 描述 |
|---|---|---|
android-notification-channel.md | CRITICAL | 创建通知渠道(Android 8.0+) |
android-permission.md | CRITICAL | POST_NOTIFICATIONS 运行时权限(Android 13+) |
android-google-services.md | CRITICAL | Firebase 项目配置 |
android-messaging-service.md | HIGH | FirebaseMessagingService 实现 |
android-notification-icon.md | MEDIUM | 通知图标资源要求 |
android-priority-high.md | HIGH | Doze 模式下的优先级 'high' |
令牌管理(token-*)
| 文件 | 影响 | 描述 |
|---|---|---|
token-registration.md | HIGH | 向后端注册令牌 |
token-refresh.md | HIGH | 令牌刷新处理 |
token-invalidation.md | MEDIUM | DeviceNotRegistered 错误处理 |
消息处理(message-*)
| 文件 | 影响 | 描述 |
|---|---|---|
message-data-vs-notification.md | CRITICAL | data 与 notification 载荷的区别 |
message-background-handler.md | HIGH | 后台消息处理 |
message-foreground-handler.md | HIGH | 前台通知显示 |
深层链接(deeplink-*)
| 文件 | 影响 | 描述 |
|---|---|---|
deeplink-navigation-conflict.md | MEDIUM | React Navigation 冲突解决 |
deeplink-terminated-state.md | MEDIUM | 应用终止时的深层链接处理 |
基础设施(infra-*)
| 文件 | 影响 | 描述 |
|---|---|---|
infra-firewall-ports.md | MEDIUM | 网络防火墙配置 |
infra-backup-fid.md | MEDIUM | 排除 Firebase Installation ID 备份 |
infra-rate-limiting.md | MEDIUM | 推送通知速率限制 |
最佳实践
| 文件 | 影响 | 描述 |
|---|---|---|
permission-timing.md | HIGH | 优化权限请求时机(70-80% 接受率) |
testing-debugging.md | HIGH | 测试工具、调试技巧、载荷验证 |
搜索规则
# Find rules by keyword
grep -l "apns" rules/
grep -l "fcm" rules/
grep -l "token" rules/
grep -l "background" rules/
grep -l "permission" rules/
grep -l "deeplink" rules/
问题 → 规则映射
| 问题 | 从此处开始 |
|---|---|
| iOS 未收到推送 | ios-apns-auth-key → ios-delegate-setup |
| Android 未收到推送 | android-google-services → android-notification-channel |
| 推送在后台无法工作 | android-priority-high → message-background-handler |
| 推送在前台不可见 | ios-foreground-display 或 message-foreground-handler |
| 令牌缺失/过期 | token-registration → token-refresh |
| 深层链接冲突错误 | deeplink-navigation-conflict |
| 通知图标异常(Android) | android-notification-icon |
| 企业网络下失败 | infra-firewall-ports |
| 未调用后台处理程序(Android) | android-priority-high → message-data-vs-notification |
| 未调用 userNotificationCenter(iOS) | ios-delegate-setup |
| 备份恢复后出现 404 错误 | infra-backup-fid |
| 发送失败(429 错误) | infra-rate-limiting |
| 权限接受率低 | permission-timing → ios-permission-request |
| 如何调试/测试推送 | testing-debugging |
| 无法在本地测试 | testing-debugging → ios-apns-auth-key |
平台特定说明
iOS(APNS)
- 需要 Apple Developer 账户和 APNs 身份验证密钥(.p8)
- Development 与 Production 构建的行为不同
- 必须先设置 Delegate,再初始化其他 SDK
- Method Swizzling 可能会干扰 Delegate 调用
Android(FCM)
- 需要从 Firebase Console 获取 google-services.json
- Android 8.0 及更高版本需要 NotificationChannel
- Android 13 及更高版本需要运行时权限
- Doze 模式下,后台处理程序需要设置
priority: 'high' - 通知图标必须为单色(透明背景上的白色)
React Native
- 常见问题:前台通知需要
gcm.message_id - 深度链接与 React Navigation 存在冲突
- 终止状态需要使用原生端 → JS 桥接模式
Expo
- ExpoPushToken 格式:
ExponentPushToken[...] - 速率限制:每个项目每秒 600 条推送通知
- SDK 53+ 需要开发构建
- 使用
eas credentials管理 APNs 密钥
完整编译文档
如需查看包含所有详细规则的完整指南:AGENTS.md
致谢
内容基于推送通知故障排查指南和 Firebase Cloud Messaging 官方文档。
评论
支持 Markdown