13. Doze模式与FCM:高优先级消息如何穿透
各位同学,今天我们来聊一个非常实际的问题——Doze模式下,FCM消息到底怎么穿透的?
说实话,这个问题我当年踩过不少坑。记得有一次,我们团队开发一款即时通讯App,测试阶段一切正常,结果一上线,用户反馈说「收不到消息了」。排查了半天,才发现是Doze模式在作祟。嗯,从那以后,我就把FCM的优先级机制研究了个底朝天。
13.1 先搞清楚:Doze模式对网络做了什么
Doze模式说白了就是系统帮你省电。它会把App的网络访问、同步、甚至闹钟都限制住。但问题是——省电和省事往往是矛盾的。
你想想看,如果用户正在等一条重要的验证码,或者一条紧急的工作消息,结果因为Doze模式延迟了半小时才收到,这体验得多糟糕?
所以Google设计了一套「优先级穿透」机制。FCM消息可以携带一个priority字段,告诉系统:「这条消息很重要,别拦着。」
13.2 FCM的两种优先级:NORMAL vs HIGH
FCM消息的优先级分为两种:
| 优先级 | 含义 | Doze模式下的行为 |
|---|---|---|
NORMAL |
普通消息,可延迟 | 会被Doze模式限制,等到维护窗口才送达 |
HIGH |
高优先级,立即送达 | 可以穿透Doze模式,系统会临时唤醒网络 |
我个人习惯是:能不用HIGH就不用。因为高优先级消息会打断Doze模式,频繁使用反而更耗电。但有些场景,比如支付通知、紧急告警,该用还得用。
13.3 高优先级消息的穿透流程
来,我们画张图,看看一条HIGH优先级消息是怎么「杀出重围」的。
看到没?关键就在那个判断节点。系统收到FCM消息后,会先检查priority字段。如果是HIGH,系统会临时唤醒网络,让消息直达App。如果是NORMAL,那就乖乖排队,等Doze的维护窗口到了再说。
13.4 代码层面怎么配?
好,理论讲完了,咱们上代码。发送FCM消息时,优先级是这样设置的:
// 服务端发送FCM消息(使用Firebase Admin SDK)
const message = {
token: '用户设备的FCM Token',
notification: {
title: '紧急通知',
body: '您的订单已发货'
},
android: {
priority: 'high', // 关键:设置为高优先级
ttl: 3600 * 1000 // 消息存活时间,单位毫秒
}
};
admin.messaging().send(message)
.then(response => {
console.log('消息发送成功:', response);
})
.catch(error => {
console.log('消息发送失败:', error);
});
客户端这边,其实不需要额外配置。只要服务端发了priority: 'high',系统会自动处理。但有一点要注意——客户端必须在AndroidManifest中声明必要的权限:
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
重要提醒:高优先级消息不等于「立即唤醒屏幕」。它只是让网络临时可用,App可以收到消息并处理。如果你想弹出通知或震动,还需要在onMessageReceived()中自行处理。
13.5 避坑指南:我曾经踩过的三个坑
讲到这里,我得分享几个实战中遇到的坑。嗯,都是真金白银换来的教训。
-
坑一:误以为HIGH优先级一定能穿透所有Doze
我曾经以为只要设了
priority: 'high',消息就一定能秒达。结果发现,在深度Doze模式下,系统还是会做一定限制。比如,如果设备长时间静止不动,系统会进入「空闲状态」,此时高优先级消息虽然能唤醒网络,但可能会有几百毫秒的延迟。所以,别指望毫秒级送达。 -
坑二:滥用HIGH优先级导致耗电飙升
有一次,我们团队把所有的FCM消息都设成了HIGH优先级。结果用户反馈手机耗电变快了。一查日志,发现设备频繁被唤醒,Doze模式几乎没生效。后来我们改成了:只有真正紧急的消息才用HIGH,其余都用NORMAL。耗电问题立刻缓解。
-
坑三:忽略TTL(Time To Live)设置
TTL是消息的存活时间。如果不设置,默认是28天。这意味着,如果用户离线了,这条消息会在FCM服务器上存28天,等用户上线后再推送。但有些场景,比如验证码,过了5分钟就没意义了。所以,一定要根据业务场景设置合理的TTL。我一般把验证码类的TTL设为5分钟,普通通知设为1小时。
个人建议:如果你不确定某条消息该不该用HIGH优先级,可以问自己一个问题:「如果这条消息延迟半小时送达,用户会骂人吗?」如果会,就用HIGH;如果不会,就用NORMAL。简单粗暴,但很有效。
13.6 总结一下
好了,今天的内容就到这里。咱们回顾一下核心要点:
- FCM的两种优先级:NORMAL(延迟送达)和HIGH(穿透Doze)
- 穿透原理:系统收到HIGH消息后,临时唤醒网络,让消息直达App
- 代码配置:服务端设置
priority: 'high',客户端声明权限 - 避坑指南:别滥用HIGH、别忽略TTL、别指望毫秒级送达
说实话,FCM的优先级机制设计得挺巧妙的。它既保证了紧急消息的及时性,又不会过度消耗电量。你想想看,如果没有这个机制,Doze模式就会变成一个「一刀切」的省电工具,用户体验反而会变差。
嗯,下一章我们聊聊更深入的话题——如何监控和调试Doze模式下的消息送达情况。到时候我会分享一些我常用的调试工具和技巧。
公众号:蓝海资料掘金营,微信deep3321