GCM高优先级消息在深度空闲模式下未收到。

17

使用以下方法进入深度空闲模式:

adb shell dumpsys deviceidle force-idle

按照文档建议,我尝试发送一个高优先级的消息到设备,使用以下代码:

{ "to" : "feoLl37Ses4:A.......hDQU1OZKd", "priority" : "high", "notification" : { "body" : "This is the body.", "title" : "this is the title", "icon" : "new" } }

但该消息没有被接收。只有在将设备状态更改为IDLE_MAINTENANCE后,才能接收到该消息。

如何让设备在处于深度空闲模式下也能接收到消息?


你使用的是什么设备?当手机处于空闲状态时,你是否安装了任何可能会杀死 Google Play 服务的任务管理器? - Alex Radzishevsky
在HTC设备上进行了一些测试。它没有安装任何任务管理器应用程序。 - SuperFrog
3个回答

5
我知道回答已经很晚了,但以防万一有人遇到同样的问题。我也遇到了同样的问题,花了几个小时尝试了几种解决方案,最终得出结论:不应该使用adb shell dumpsys deviceidle force-idle进入深度空闲模式来测试推送通知,因为它们根本不会被接收(除非你执行unforce命令,否则你的设备将被强制进入深度空闲模式)。
如果您想在深度空闲模式下测试高优先级的推送通知,请改用adb shell dumpsys deviceidle step通过所有步骤,直到达到深度空闲模式。以下是一个示例。
adb shell dumpsys deviceidle get light
ACTIVE
adb shell dumpsys deviceidle step
Stepped to deep: IDLE_PENDING
adb shell dumpsys deviceidle get light
INACTIVE
adb shell dumpsys deviceidle step
Stepped to deep: SENSING
adb shell dumpsys deviceidle step
Stepped to deep: LOCATING
adb shell dumpsys deviceidle step
Stepped to deep: IDLE
adb shell dumpsys deviceidle get light
OVERRIDE
adb shell dumpsys deviceidle get deep
IDLE

这样,您将进入深度休眠模式,就像在实际情况下一样,您的推送将按预期接收。请注意,在调用步骤命令之前,您应执行adb shell dumpsys battery unplug并关闭设备屏幕。
我猜adb shell dumpsys deviceidle force-idle更强大,因为它即使设备屏幕开启也会强制进入空闲模式。当官方安卓文档说“您可以通过以下步骤测试Doze模式:”并告诉您使用force-idle命令时,这是完全误导的。因为这个force-idle不像真正的那样工作,并且没有任何关于此的免责声明。

1

您需要使用WakefulBroadcastReceiver来启动执行任务的服务,该类使用startWakefulService()方法进行启动。 该方法类似于startService(),但是当服务启动时,WakefulBroadcastReceiver会持有唤醒锁。 通过startWakefulService()传递的意图包含一个额外的标识唤醒锁的参数。

步骤1: 继承WakefulBroadcastReceiver而不是BroadcastReceiver。

步骤2: 在onReceive()中调用startWakefulService。

如有疑问,请告知。


我认为WakefulBroadcastReceiver不会有帮助,因为它只是在接收广播后保持设备唤醒的。 - SuperFrog

1
如果您想唤醒应用程序以从Doze状态中接收消息,请使用 setAndAllowWhileIdle() setExactAndAllowWhileIdle() 。当您执行命令时,您的应用程序进入了Doze模式。
adb shell dumpsys deviceidle force-idle

以下是设备进入Doze模式时可能会影响应用的限制:
  1. 网络访问被暂停。
  2. 系统忽略唤醒锁。
  3. 标准AlarmManager警报(包括setExact()和setWindow())推迟到下一个维护窗口。
  4. 如果需要在Doze模式下触发警报,请使用setAndAllowWhileIdle()或setExactAndAllowWhileIdle()。
  5. 使用setAlarmClock()设置的警报继续正常触发 —— 系统会在这些警报触发前不久退出Doze模式。
  6. 系统不执行Wi-Fi扫描。
  7. 系统不允许同步适配器运行。
  8. 系统不允许JobScheduler运行。
此外,Doze模式对网络访问的限制也可能影响您的应用程序,尤其是如果应用程序依赖于实时消息,则需注意。如果您的应用程序需要持久连接到网络以接收消息,则应尽可能使用 Firebase Cloud Messaging (FCM)。 为了帮助安排警报,Android 6.0 (API级别23)引入了两个新的AlarmManager方法:setAndAllowWhileIdle() 和setExactAndAllowWhileIdle()。通过这些方法,可以设置即使设备处于Doze模式中,警报仍能触发的警报。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接