Firebase onMessageReceived()带Data Payload杀后台后部分设备不触发,如何显示通知?
我之前也碰到过这个糟心的问题!国内很多定制ROM(比如小米、华为、OPPO这些)对后台进程限制特别严,就算你发的是纯Data消息,杀后台后Firebase的MessagingService可能根本起不来。下面是我亲测有效的几个方案:
可行解决方案
1. 适配厂商后台白名单
这是最关键的一步!国内几乎所有定制ROM都有后台管理机制,你得引导用户把你的App加到后台保护白名单或者自启动权限里。
- 不同厂商的操作路径不一样,比如:
- 小米:设置 → 应用设置 → 你的App → 省电策略 → 无限制
- 华为:设置 → 应用和服务 → 应用启动管理 → 关闭自动管理,手动打开允许自启动、允许后台活动
- OPPO/VIVO:设置 → 电池 → 应用耗电管理 → 你的App → 允许后台耗电
- 代码里可以做个品牌检测逻辑,弹出对应指引页面,告诉用户怎么操作,降低用户的操作门槛。
2. 使用混合消息(Data + Notification Payload)
虽然纯Data消息理论上应该触发onMessageReceived(),但有些厂商杀后台后,系统会把纯Data消息拦截,反而带Notification字段的混合消息能被系统通知栏直接接收。
- 发送消息时同时包含
notification和data字段,示例如下:{ "to": "DEVICE_TOKEN", "notification": { "title": "新消息提醒", "body": "您有一条未读消息" }, "data": { "message_id": "12345", "type": "chat" } } - 这种情况下,不管App在前台还是后台,通知都会先显示在系统栏,用户点击后会启动App,你可以在启动的Activity里通过
getIntent().getExtras()拿到data里的内容。
3. 利用前台服务保活(谨慎使用)
如果你的App有合理的后台需求(比如即时通讯、实时监控类),可以启动一个前台服务,这样厂商的后台管理一般不会轻易杀掉你的进程。
- 注意Android 8.0+要求前台服务必须显示一个持续的通知,你可以做个低调的通知,比如显示“App后台运行中”之类的内容。
- 代码示例(Kotlin):
class KeepAliveService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { val notification = NotificationCompat.Builder(this, "BACKGROUND_CHANNEL") .setContentTitle("App后台运行中") .setSmallIcon(R.drawable.ic_notification) .setPriority(NotificationCompat.PRIORITY_LOW) .build() startForeground(1001, notification) return START_STICKY } override fun onBind(intent: Intent?): IBinder? = null } - 别忘了在Manifest里注册服务,并申请
FOREGROUND_SERVICE权限。
4. 设置高优先级消息
发送消息时设置priority: "high"(仅针对Android平台),这样系统会更优先处理这条消息,减少被拦截的概率。
- 示例:
{ "to": "DEVICE_TOKEN", "priority": "high", "data": { "key": "value" } } - 注意高优先级消息不能滥用,否则可能被系统限流,影响消息送达率。
5. 测试时关闭省电模式
很多用户开启了省电模式,这会进一步限制后台进程的运行,测试时一定要先关闭省电模式再验证,不然可能误以为是代码逻辑问题。
这些方案不能保证100%覆盖所有设备,但能解决大部分场景下的通知显示问题,毕竟厂商的后台限制规则一直在变,只能尽量适配~
内容的提问来源于stack exchange,提问作者Faisal Shaikh
相关产品推荐
相关产品推荐

