Firebase Cloud Messaging (FCM) 推送常见问题汇集

近期一直在做Google的FCM推送工作,遇到不少坑,也遇到各种神奇事情.项目最近出街了,终于有空总结一下,算是造福国内开发者吧,FCM在国内的讨论相对比较少.
本文旨在描述常见问题,并非开发guide

Q: APP为什么有时候能够收到消息,有时候收不到消息?
A: FCM 分为两种接收消息的方式, 前台接收 后台接收 .

FCM 传送主题消息的方式与传送其他下行消息的方式相同。 [1]
如需接收消息,请使用继承 FirebaseMessagingService 的服务。 您的服务应该重写 onMessageReceived onDeletedMessages 回调方法。该服务应在收到消息后 20 秒内对其进行处理(Android Marshmallow 上为 10 秒)。这个时长可能会更短,具体取决于调用 onMessageReceived 之前发生的操作系统延迟。这个时间段过后,各种操作系统行为(如 Android O 的 后台执行限制 )可能会影响您完成工作的能力。如需了解详情,请参阅我们的 消息优先级 概述。
大多数类型的消息都会提供 onMessageReceived ,但以下情况例外:

  • 当应用在后台时送达的通知消息 。在这种情况下,通知将传送至设备的系统任务栏。默认情况下,用户点按通知即可打开应用启动器。

  • 在后台所接收的同时具备通知和数据载荷的消息 。 在这种情况下,通知将传送至设备的系统任务栏,数据载荷则传送至启动器 Activity 的 intent 的 extras 属性中。

    Q: 为什么我按照答案1做完之后还是不行?
    A: 请检查推送过来的数据格式是否正确,正确的格式应该是以下这样的 [2]
    包含 notification data ,需要显示的 title body 应该包含在 notification 里面,不要放到其他地方. 如果只在 data 那里有内容, notification 那里没有内容的话, 一般是不会收到消息的. [4]

    请确保未在自定义键值对中使用任何保留字词。保留字词包括 “from”、“notification”、“message_type” 或以 “google” 或 “gcm” 开头的任何字词。

    "message":{ "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...", "notification":{ "title":"Portugal vs. Denmark", "body":"great match!" "data" : { "Nick" : "Mario", "Room" : "PortugalVSDenmark"
  • Q: 为什么Debug的时候发现能够收到消息,但是没有去到 onMessageReceived ?
    A: 后台收到消息的话,不会去 onMessageReceived ,而是走后台的方式.更多参考问题1

  • Q: 为什么开了VPN还是拿不到 firebase token?
    A: 不是所有VPN都可以成功拿到firebase token. 目前来说,Lantern是已知拿到firebase token成功率比较高的VPN工具.
    具体验证方法,打开VPN后,能够打开Google Play Store,并成功浏览的VPN,一般无问题.

  • Q: 为什么某些手机关了APP后总是收不到消息?

  • 请看答案2

  • 有些第三方厂商会设置电源模式,会限制APP的通讯,可以打开电源管理,之后选择[无限制]后再去尝试,还有[自启动]管理,需要都打开(已知厂商: 华为/OPPO/小米),小米打开[自启动]即可收到消息. [7]
    具体验证方法如下:

    输入 adb shell dumpsys package "包名" | grep stopped
    之后console输出User 0: ceDataInode=249503 installed=true hidden=false suspended=false distractionFlags=0 stopped=true notLaunched=false enabled=0 instant=false virtual=false
    如果 stopped true ,则收不到的,如果 stopped false 则是可以收到的.

  • 如果是中国国内的手机,不是所有国内手机都有安装GMS,没有安装GMS套装的手机,kill APP后的确不会接收FCM的消息推送.

  • FCM的推送率其实也不是百分百的,不要给PO/BA打包票

  • 部分国行三星机器会因为功率原因,会block FCM server,留意留意!

  • Q: 为什么接收消息的图标不对,显示为一个灰色的图标,或者显示为APP的图标icon?
    A: 当后台接收消息时,会使用默认的图标,没有的话会使用APP的icon.
    将以下代码行添加到 application 标记内,以设置自定义默认图标和颜色:

  • <!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
         See README(https://goo.gl/l4GJaQ) for more. -->
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_stat_ic_notification" />
    <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
         notification message. See README(https://goo.gl/6BKBk7) for more. -->
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorAccent" />
    
  • Q: 设置了图标是彩色的,推送过来后显示的图标是一片灰色的?
    A: 叫UI designer 提供灰色透明底的PNG图片,之后再去set color即可.
    NotificationCompat.Builder().setColor()

  • Q: 为什么通过postman FCM server 推送消息给手机, 试着试着手机就收不到了?
    A: 不要经常发同一内容的消息到同一台手机,会被FCM block的.可以改一改推送内容,又或者卸载APP(firebase token会改变)再重装即可.

  • Q: 为什么kill APP后,已经收到的消息会消失(即在系统通知栏中的消息会消失)?
    A: 这是部分厂商的行为,淘宝/微博国际版也是一样.已知厂商:小米/三星
    部分厂商应该是对NotificationManager做了一些处理导致的,APP可以做的就只能搞很复杂的跨进程推送.

  • Q: 为什么本地build的开发APP无问题,实际生产环境就收不到推送?
    A: 请保证包名无问题,实际生产环境使用的推送key也是对应production包名用的key

  • 接收和处理主题消息
  • 数据格式结构
  • 修改应用清单