客户端显示前过滤Firebase通知:应用终止场景如何实现?
Firebase 未运行状态下的客户端通知过滤方案
针对你提到的应用未运行(terminated)时无法过滤通知的问题,需按 Android 和 iOS 两个平台分别处理,核心思路是绕开系统直接处理通知的逻辑,把控制权拿回客户端:
Android 平台
- 强制用数据消息推送:让服务器只发送含
data字段的消息(不要带notification字段)。这种情况下,不管应用是前台、后台还是未运行状态,都会触发自定义FirebaseMessagingService的onMessageReceived方法。 - 在服务中做过滤:重写
onMessageReceived方法,先通过BuildConfig.DEBUG判断当前是调试版还是生产版,再读取消息data里的服务器标识(比如server_type: "production"),如果是调试版收到生产服务器的消息,直接跳过通知创建逻辑即可。 - Manifest 配置注意:确保
FirebaseMessagingService在Manifest里正确注册,且android:exported="true"(适配Android 12+的权限要求)。
iOS 平台
iOS 的限制更多,分两种方案:
方案1:使用 UNNotificationServiceExtension(推荐)
这是唯一能在系统展示通知前拦截所有类型推送(包括带notification字段的消息)的方式,不管应用是否运行:
- 在Xcode中添加
UNNotificationServiceExtension目标; - 在扩展的
didReceiveNotificationRequest:withContentHandler:方法中,先判断当前是调试版还是生产版(用预编译宏#if DEBUG),再读取推送内容里的服务器标识; - 如果是调试版收到生产服务器的消息,直接调用
contentHandler(nil)或者传入一个空的UNMutableNotificationContent,系统就不会展示这条通知; - 注意:扩展的签名和主应用要保持一致,且需要在主应用的Info.plist中声明扩展的NSExtension属性。
方案2:仅发送静默推送
让服务器发送带content-available: 1的静默推送(仅含data字段),这种推送会唤醒未运行的应用一小段时间:
- 在AppDelegate的
didReceiveRemoteNotification:fetchCompletionHandler:方法中处理消息,判断调试版和服务器标识,决定是否本地创建通知; - 缺点:需要用户开启“后台应用刷新”权限,且静默推送的频率有苹果的限制,不能保证100%触发。
通用注意事项
- 必须在推送消息中加入服务器类型标识(比如
server_env: "prod"或dev"),客户端才能准确判断是否过滤; - 调试版的判断逻辑要依赖平台原生的标识(Android的
BuildConfig.DEBUG、iOS的DEBUG宏),不要用自定义配置,避免打包出错; - 尽量统一推送格式为仅
data字段,这样前后台、未运行状态的处理逻辑可以统一,减少适配成本。
内容的提问来源于stack exchange,提问作者andynewman
相关产品推荐
相关产品推荐

