push-notification-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Push Notification Best Practices

推送通知最佳实践

Overview

概述

Comprehensive guide for implementing and troubleshooting push notifications in mobile applications. Covers iOS (APNS), Android (FCM), React Native, Expo, and Flutter platforms with platform-specific configurations, token management, message handling, and deep linking patterns.
移动端应用推送通知的实现与排查全面指南,涵盖iOS(APNS)、Android(FCM)、React Native、Expo及Flutter平台,包含平台专属配置、令牌管理、消息处理与深度链接模式。

Platform Support Matrix

平台支持矩阵

PlatformOffline PushNotification BarClick NavigationIn-App ToastBackground Handler
iOSAPNSSystemDeep LinkCustomdata-only payload
AndroidFCMSystemIntentCustomdata-only payload
React NativeAPNS/FCMSystemReact NavigationCustomsetBackgroundMessageHandler
ExpoExpo PushSystemLinkingCustomTaskManager
FlutterAPNS/FCMSystemNavigatorCustomonBackgroundMessage
平台离线推送通知栏点击导航应用内提示框后台处理器
iOSAPNS系统级深度链接自定义仅数据负载
AndroidFCM系统级Intent自定义仅数据负载
React NativeAPNS/FCM系统级React Navigation自定义setBackgroundMessageHandler
ExpoExpo Push系统级Linking自定义TaskManager
FlutterAPNS/FCM系统级Navigator自定义onBackgroundMessage

Decision Trees

决策树

Permission Request Timing

权限申请时机

When to request notification permission?
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]
TimingAcceptance RateUse Case
Immediate (app launch)15-20%Low engagement apps
After onboarding40-50%Standard apps
User-initiated action70-80%High engagement apps
Recommendation: Request after explaining value or when user enables a related feature.
何时申请通知权限?
用户安装应用
        |
        v
  [首次启动?] ──是──> [先展示价值主张]
        |                          |
        否                         v
        |                  [用户操作触发需求?]
        v                          |
  [已授权?]              是
        |                          |
       是                         v
        |                  [申请权限] ──> 70-80%接受率
        v
  [通知功能就绪]
时机接受率使用场景
立即申请(应用启动时)15-20%低活跃度应用
引导流程后申请40-50%标准应用
用户主动操作后申请70-80%高活跃度应用
推荐方案: 先解释通知功能价值,或在用户启用相关功能后再申请权限。

Silent vs Visible Notification

静默通知 vs 可见通知

Which payload type should I use?
[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)
ScenarioPayload TypeReason
New message alertVisibleUser needs immediate attention
Order status updateVisibleTime-sensitive information
Background syncSilentNo user interruption needed
Custom notification UISilentFull control over display
Update badge countSilentBackground processing needed
应使用哪种负载类型?
[使用目的是什么?]
        |
        +──> 时间敏感型用户提醒 ──> 可见通知(通知负载)
        |
        +──> 后台数据同步 ──> 静默通知(仅数据负载)
        |
        +──> 需要自定义UI ──> 静默通知(仅数据负载)
        |
        +──> 需要后台处理 ──> 静默通知(仅数据负载)
场景负载类型原因
新消息提醒可见通知用户需要立即关注
订单状态更新可见通知时间敏感型信息
后台同步静默通知无需打扰用户
自定义通知UI静默通知完全控制显示样式
更新角标计数静默通知需要后台处理

Extension Strategy (iOS)

扩展策略(iOS)

When to use Notification Service Extension?
  • Need to modify notification content before display
  • Need to download and attach media (images, videos)
  • Need to decrypt end-to-end encrypted payloads
  • Need to add action buttons dynamically
When to use Notification Content Extension?
  • Need custom notification UI beyond system template
  • Need interactive elements in expanded view
何时使用Notification Service Extension?
  • 需要在通知显示前修改内容
  • 需要下载并附加媒体(图片、视频)
  • 需要解密端到端加密的负载
  • 需要动态添加操作按钮
何时使用Notification Content Extension?
  • 需要超出系统模板的自定义通知UI
  • 需要在展开视图中添加交互元素

Anti-patterns (NEVER Do)

反模式(绝对不要做)

Permission Handling

权限处理

NEVERWhyInstead
Request permission on first launch without context15-20% acceptance rateExplain value first, then request
Re-ask after user deniesSystem ignores repeated requestsShow settings redirect
Ignore provisional authorizationMisses iOS 12+ quiet deliveryUse
.provisional
option
绝对不要原因替代方案
首次启动无上下文就申请权限接受率仅15-20%先解释价值,再申请权限
用户拒绝后重复申请系统会忽略重复请求引导用户前往设置开启
忽略临时授权错过iOS 12+的静默推送功能使用
.provisional
选项

Token Management

令牌管理

NEVERWhyInstead
Cache tokens long-termTokens can change on reinstall/restoreAlways use fresh token from callback
Assume token formatFormat varies by platform/SDKTreat as opaque string
Send token without user associationCan't target notificationsAssociate with userId on backend
Store tokens without device IDDuplicate tokens per userUse deviceId as unique key
绝对不要原因替代方案
长期缓存令牌重装/恢复设备后令牌会变更始终使用回调返回的新鲜令牌
假设令牌格式固定格式因平台/SDK而异将其视为不透明字符串
发送未关联用户的令牌无法精准推送通知在后端将令牌与userId关联
存储令牌时不关联设备ID同一用户可能有重复令牌使用deviceId作为唯一标识

Message Handling

消息处理

NEVERWhyInstead
Use
notification
payload for background processing
onMessageReceived not called in backgroundUse data-only payload
Rely on silent notifications for time-critical deliveryDelivery not guaranteedUse visible notifications
Execute heavy operations in background handlerSystem kills app after ~30 secondsQueue work, process quickly
Forget to handle both payload typesMissing notificationsHandle notification + data payloads
绝对不要原因替代方案
使用
notification
负载进行后台处理
后台不会触发onMessageReceived使用仅数据负载
依赖静默通知实现时间敏感型推送送达无法保证使用可见通知
在后台处理器中执行重操作系统会在约30秒后杀死应用任务入队,快速处理
忘记同时处理两种负载类型会遗漏通知同时处理通知负载与数据负载

iOS Specific

iOS专属

NEVERWhyInstead
Register for notifications before delegate setupDelegate methods not calledSet delegate before
registerForRemoteNotifications()
Skip
serviceExtensionTimeWillExpire()
implementation
Content modification failsAlways implement fallback
Use .p12 certificatesExpires yearly, deprecatedUse .p8 authentication key
绝对不要原因替代方案
未设置代理就注册通知代理方法不会被调用
registerForRemoteNotifications()
前设置代理
不实现
serviceExtensionTimeWillExpire()
内容修改会失败始终实现降级方案
使用.p12证书每年过期且已被弃用使用.p8认证密钥

Android Specific

Android专属

NEVERWhyInstead
Skip NotificationChannel creationNotifications don't appear on Android 8.0+Create channel at app start
Use priority
normal
for background handlers
Doze mode blocks deliveryUse priority
high
Use colored notification iconsAndroid ignores colors, shows white squareUse white-on-transparent icons
绝对不要原因替代方案
不创建NotificationChannelAndroid 8.0+上通知不会显示应用启动时创建渠道
后台处理器使用
normal
优先级
休眠模式会阻止送达使用
high
优先级
使用彩色通知图标Android会忽略颜色,显示白色方块使用白底透明图标

Skill Format

规则格式

Each rule file follows a hybrid format for fast lookup and deep understanding:
  • Quick Pattern: Incorrect/Correct code snippets for immediate pattern matching
  • When to Apply: Situations where this rule is relevant
  • Deep Dive: Full context with step-by-step guides and platform-specific details
  • Common Pitfalls: Common mistakes and how to avoid them
  • Related Rules: Cross-references to related patterns
Impact ratings: CRITICAL (fix immediately), HIGH (significant improvement), MEDIUM (worthwhile optimization)
每个规则文件采用混合格式,兼顾快速查询与深度理解:
  • 快速模式:错误/正确代码片段,用于即时匹配模式
  • 适用场景:该规则的适用情况
  • 深度解析:完整上下文,含分步指南与平台专属细节
  • 常见陷阱:常见错误及规避方法
  • 相关规则:关联模式的交叉引用
影响等级:CRITICAL(立即修复)、HIGH(显著改进)、MEDIUM(值得优化)

When to Apply

适用场景

Reference these guidelines when:
  • Setting up push notifications in a mobile app
  • Debugging push notification delivery issues
  • Implementing background notification handlers
  • Integrating deep linking with push notifications
  • Managing push tokens and device registration
  • Troubleshooting platform-specific push issues
  • Reviewing push notification code for reliability
以下场景可参考本指南:
  • 移动端应用推送通知搭建
  • 推送通知送达问题调试
  • 后台通知处理器实现
  • 推送通知与深度链接集成
  • 推送令牌与设备注册管理
  • 平台专属推送问题排查
  • 推送通知代码可靠性评审

Priority-Ordered Guidelines

优先级排序指南

PriorityCategoryImpactPrefix
1iOS SetupCRITICAL
ios-
2Android SetupCRITICAL
android-
3Token ManagementHIGH
token-
4Message HandlingHIGH
message-
5Deep LinkingMEDIUM
deeplink-
6InfrastructureMEDIUM
infra-
优先级分类影响等级前缀
1iOS配置CRITICAL
ios-
2Android配置CRITICAL
android-
3令牌管理HIGH
token-
4消息处理HIGH
message-
5深度链接MEDIUM
deeplink-
6基础设施MEDIUM
infra-

Quick Reference

快速参考

Critical: iOS Setup

关键:iOS配置

Setup checklist:
  • Generate APNs authentication key (.p8) from Apple Developer
  • Upload to Firebase Console with Key ID and Team ID
  • Enable Push Notifications capability in Xcode
  • Set UNUserNotificationCenter delegate in didFinishLaunchingWithOptions
  • Request notification authorization before registering
  • Implement foreground presentation options
配置清单:
  • 从Apple Developer生成APNs认证密钥(.p8)
  • 上传至Firebase控制台,填写Key ID与Team ID
  • 在Xcode中启用Push Notifications能力
  • 在didFinishLaunchingWithOptions中设置UNUserNotificationCenter代理
  • 注册前申请通知授权
  • 实现前台展示选项

Critical: Android Setup

关键:Android配置

Setup checklist:
  • Add google-services.json to app/ directory
  • Apply google-services Gradle plugin
  • Create NotificationChannel (Android 8.0+)
  • Request POST_NOTIFICATIONS permission (Android 13+)
  • Implement FirebaseMessagingService
  • Set notification icon (transparent background + white)
  • Use priority 'high' for Doze mode compatibility
配置清单:
  • 将google-services.json添加至app/目录
  • 应用google-services Gradle插件
  • 创建NotificationChannel(Android 8.0+)
  • 申请POST_NOTIFICATIONS权限(Android 13+)
  • 实现FirebaseMessagingService
  • 设置通知图标(透明背景+白色)
  • 使用'high'优先级以兼容休眠模式

High: Token Management

重要:令牌管理

Token lifecycle:
javascript
// 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);
}
令牌生命周期:
javascript
// 1. 向服务器注册令牌
const token = await getToken();
await registerToken(token, userId);

// 2. 处理令牌刷新
onTokenRefresh((newToken) => {
  updateTokenOnServer(newToken, userId);
});

// 3. 处理令牌失效
if (error.code === 'DeviceNotRegistered') {
  deleteTokenFromDatabase(token);
}

High: Message Handling

重要:消息处理

Payload types:
  • data-only: Background handler runs on both platforms
  • notification + data: iOS/Android behavior differs
    • iOS: Always shows notification
    • Android: Background = system tray, Foreground = onMessageReceived
Priority settings:
  • Use
    priority: 'high'
    for time-sensitive notifications
  • Required for Android Doze mode background handlers
负载类型:
  • 仅数据负载:前后台处理器在双平台均会运行
  • 通知+数据负载:iOS/Android行为不同
    • iOS:始终显示通知
    • Android:后台=系统托盘,前台=触发onMessageReceived
优先级设置:
  • 时间敏感型通知使用
    priority: 'high'
  • Android休眠模式下的后台处理器必须设置该优先级

Rules

规则

Full documentation with code examples in
rules/
:
含代码示例的完整文档位于
rules/
目录:

iOS Setup (
ios-*
)

iOS配置 (
ios-*
)

FileImpactDescription
ios-apns-auth-key.md
CRITICALAPNs authentication key setup
ios-delegate-setup.md
CRITICALUNUserNotificationCenter delegate configuration
ios-permission-request.md
CRITICALNotification permission request flow
ios-token-registration.md
HIGHAPNS token registration and handling
ios-foreground-display.md
HIGHDisplay notifications in foreground
ios-method-swizzling.md
MEDIUMMethod Swizzling management
ios-extension-build.md
MEDIUMNotification Service Extension setup
文件影响等级描述
ios-apns-auth-key.md
CRITICALAPNs认证密钥配置
ios-delegate-setup.md
CRITICALUNUserNotificationCenter代理配置
ios-permission-request.md
CRITICAL通知权限申请流程
ios-token-registration.md
HIGHAPNS令牌注册与处理
ios-foreground-display.md
HIGH前台通知展示
ios-method-swizzling.md
MEDIUM方法混写管理
ios-extension-build.md
MEDIUMNotification Service Extension配置

Android Setup (
android-*
)

Android配置 (
android-*
)

FileImpactDescription
android-notification-channel.md
CRITICALNotification channel creation (Android 8.0+)
android-permission.md
CRITICALPOST_NOTIFICATIONS runtime permission (Android 13+)
android-google-services.md
CRITICALFirebase project configuration
android-messaging-service.md
HIGHFirebaseMessagingService implementation
android-notification-icon.md
MEDIUMNotification icon asset requirements
android-priority-high.md
HIGHPriority 'high' for Doze mode
文件影响等级描述
android-notification-channel.md
CRITICALNotificationChannel创建(Android 8.0+)
android-permission.md
CRITICALPOST_NOTIFICATIONS运行时权限(Android 13+)
android-google-services.md
CRITICALFirebase项目配置
android-messaging-service.md
HIGHFirebaseMessagingService实现
android-notification-icon.md
MEDIUM通知图标资源要求
android-priority-high.md
HIGH高优先级配置以兼容休眠模式

Token Management (
token-*
)

令牌管理 (
token-*
)

FileImpactDescription
token-registration.md
HIGHToken registration with backend
token-refresh.md
HIGHToken refresh handling
token-invalidation.md
MEDIUMDeviceNotRegistered error handling
文件影响等级描述
token-registration.md
HIGH令牌与后端注册
token-refresh.md
HIGH令牌刷新处理
token-invalidation.md
MEDIUMDeviceNotRegistered错误处理

Message Handling (
message-*
)

消息处理 (
message-*
)

FileImpactDescription
message-data-vs-notification.md
CRITICALdata vs notification payload differences
message-background-handler.md
HIGHBackground message processing
message-foreground-handler.md
HIGHForeground notification display
文件影响等级描述
message-data-vs-notification.md
CRITICAL数据负载与通知负载的差异
message-background-handler.md
HIGH后台消息处理
message-foreground-handler.md
HIGH前台通知展示

Deep Linking (
deeplink-*
)

深度链接 (
deeplink-*
)

FileImpactDescription
deeplink-navigation-conflict.md
MEDIUMReact Navigation conflict resolution
deeplink-terminated-state.md
MEDIUMDeep link handling when app is terminated
文件影响等级描述
deeplink-navigation-conflict.md
MEDIUMReact Navigation冲突解决
deeplink-terminated-state.md
MEDIUM应用终止状态下的深度链接处理

Infrastructure (
infra-*
)

基础设施 (
infra-*
)

FileImpactDescription
infra-firewall-ports.md
MEDIUMNetwork firewall configuration
infra-backup-fid.md
MEDIUMFirebase Installation ID backup exclusion
infra-rate-limiting.md
MEDIUMPush notification rate limiting
文件影响等级描述
infra-firewall-ports.md
MEDIUM网络防火墙配置
infra-backup-fid.md
MEDIUMFirebase安装ID备份排除
infra-rate-limiting.md
MEDIUM推送通知频率限制

Best Practices

最佳实践

FileImpactDescription
permission-timing.md
HIGHPermission request timing optimization (70-80% acceptance)
testing-debugging.md
HIGHTesting tools, debugging techniques, payload validation
文件影响等级描述
permission-timing.md
HIGH权限申请时机优化(70-80%接受率)
testing-debugging.md
HIGH测试工具、调试技巧、负载验证

Searching Rules

规则搜索

bash
undefined
bash
undefined

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/
undefined
grep -l "apns" rules/ grep -l "fcm" rules/ grep -l "token" rules/ grep -l "background" rules/ grep -l "permission" rules/ grep -l "deeplink" rules/
undefined

Problem → Rule Mapping

问题→规则映射

ProblemStart With
iOS not receiving push
ios-apns-auth-key
ios-delegate-setup
Android not receiving push
android-google-services
android-notification-channel
Push not working in background
android-priority-high
message-background-handler
Push not visible in foreground
ios-foreground-display
or
message-foreground-handler
Token missing/expired
token-registration
token-refresh
Deep link conflict error
deeplink-navigation-conflict
Notification icon broken (Android)
android-notification-icon
Failed on corporate network
infra-firewall-ports
Background handler not called (Android)
android-priority-high
message-data-vs-notification
userNotificationCenter not called (iOS)
ios-delegate-setup
404 error after backup restore
infra-backup-fid
Send failed (429 error)
infra-rate-limiting
Low permission acceptance rate
permission-timing
ios-permission-request
How to debug/test push
testing-debugging
Cannot test locally
testing-debugging
ios-apns-auth-key
问题从以下规则开始排查
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
iOS的userNotificationCenter未触发
ios-delegate-setup
备份恢复后出现404错误
infra-backup-fid
发送失败(429错误)
infra-rate-limiting
权限接受率低
permission-timing
ios-permission-request
如何调试/测试推送
testing-debugging
无法本地测试
testing-debugging
ios-apns-auth-key

Platform-Specific Notes

平台专属说明

iOS (APNS)

iOS (APNS)

  • Requires Apple Developer account and APNs authentication key (.p8)
  • Different behavior for Development vs Production builds
  • Delegate must be set before other SDK initialization
  • Method Swizzling can interfere with delegate calls
  • 需要Apple开发者账号与APNs认证密钥(.p8)
  • 开发版与生产版构建的行为不同
  • 必须在其他SDK初始化前设置代理
  • 方法混写可能干扰代理调用

Android (FCM)

Android (FCM)

  • Requires google-services.json from Firebase Console
  • NotificationChannel required for Android 8.0+
  • Runtime permission required for Android 13+
  • Doze mode requires
    priority: 'high'
    for background handlers
  • Notification icons must be monochrome (white on transparent)
  • 需要从Firebase控制台获取google-services.json
  • Android 8.0+必须创建NotificationChannel
  • Android 13+需要运行时权限
  • 休眠模式下后台处理器需要设置
    priority: 'high'
  • 通知图标必须为单色(白底透明)

React Native

React Native

  • Common issue:
    gcm.message_id
    required for foreground notifications
  • Deep linking conflicts with React Navigation
  • Terminated state requires native → JS bridge pattern
  • 常见问题:前台通知需要
    gcm.message_id
  • 深度链接与React Navigation存在冲突
  • 应用终止状态下需要原生→JS桥接模式

Expo

Expo

  • ExpoPushToken format:
    ExponentPushToken[...]
  • Rate limit: 600 push notifications per second per project
  • Development builds required for SDK 53+
  • Use
    eas credentials
    for APNs key management
  • ExpoPushToken格式:
    ExponentPushToken[...]
  • 频率限制:每个项目每秒最多600条推送通知
  • SDK 53+需要使用开发构建版本
  • 使用
    eas credentials
    管理APNs密钥

Full Compiled Document

完整编译文档

For the complete guide with all rules expanded:
AGENTS.md
包含所有规则详情的完整指南:
AGENTS.md

Attribution

参考来源

Based on push notification troubleshooting guides and Firebase Cloud Messaging official documentation.
基于推送通知排查指南与Firebase Cloud Messaging官方文档整理。