API 29/30设备上FCM带图推送偶发不显示图片的问题咨询
带图片FCM通知在Android API 29/30偶发图片为空的修复方案
你遇到的「系统识别到通知附带图片,但展开后图片空白、文本正常」的现象,本质是通知大图的Bitmap在系统渲染前未完成加载、或已被内存回收——high优先级仅保障通知能及时弹出,不承担通知自定义大视图资源的加载保障,这个在API 29/30的后台限制收紧阶段非常常见。
优先落地的修复方案(按优先级排序)
1. 弃用FCM通知消息的内置image字段,改用纯数据消息手动构建通知
这是该问题最核心的解决方向:
- FCM服务端payload里自带
notification标签的通知消息,其中的image字段是系统级FCM客户端自动拉取并渲染的,这个过程会受API 29/30的后台网络限制,哪怕推流设为high优先级,也会出现拉取超时、Bitmap加载失败、被系统内存回收的问题,且你完全无法干预这个拉取过程的重试逻辑。 - 改用纯数据消息(payload仅携带图片URL、文本、跳转链接等自定义字段,不带FCM的
notification标签),在自己实现的FirebaseMessagingService#onMessageReceived回调里手动拉取图片、构建通知。这个拉取过程属于应用自身的行为,不受系统FCM客户端的后台网络约束,你可以自定义超时、重试逻辑。
注意:纯数据消息在应用处于后台/被杀状态时,只有high优先级的推送才能唤醒
onMessageReceived,你当前已经设置high优先级,刚好满足这个要求。
2. 手动构建通知时增加图片加载的降级与缓存逻辑
哪怕改用手动拉取,弱网、内存不足的场景依然可能导致偶发失败,需要加两层兜底:
- 本地磁盘缓存:图片拉取成功后存入应用私有缓存目录,后续相同URL的通知直接读取本地缓存,无需重复拉取。
- 超时降级:系统渲染通知的窗口通常只有1s左右,若拉取大图超过1.5s仍未完成,先弹出仅带文本的通知;等图片加载完成后,用相同的通知ID调用
NotificationManager#notify更新通知,再补上大图。 - 压缩Bitmap采样率:不要直接加载原图,通过
BitmapFactory.Options#inSampleSize把图片压缩到通知适配的尺寸(宽度1080px以内即可),避免内存不足被系统回收。
3. 适配API 29/30的省电与后台限制规则
你推测的省电模式、应用待机模式确实是诱因之一,但high优先级仅豁免通知弹出延迟,不豁免CPU休眠、网络访问的限制:
- 在
onMessageReceived里拉取图片的过程中,临时申请持有PowerManager.WakeLock,持有时长控制在1~2s即可,确保CPU不会在拉取图片的过程中休眠,用完立刻释放避免泄漏。 - 所有要展示在通知里的图片,必须先下载到本地、转成可用的Bitmap后再传给
NotificationCompat.BigPictureStyle,绝对不能在RemoteViews里直接加载网络图片。
4. 容易遗漏的坑点排查
- 校验通知渠道的优先级:Android 8.0之后,通知的实际优先级是「全局推送优先级」和「通知渠道优先级」的较低值,若你创建通知渠道时的
setImportance设置为低于IMPORTANCE_HIGH,哪怕推送设为high,也会被降级,进而触发后台限制。 - 不要复用通知构建实例:每次更新带图通知时,要重新创建
NotificationCompat.Builder实例,避免系统缓存旧的空Bitmap。 - 设置大图前做合法性校验:传入
BigPictureStyle前,判断bitmap != null && !bitmap.isRecycled(),避免把已回收的无效对象传给系统渲染。
内容的提问来源于stack exchange,提问作者dodo_zito
相关产品推荐
相关产品推荐

