推送消息无法立即启动服务

时间:2018-01-26 13:33:36

标签: android push-notification geolocation firebase-cloud-messaging

上下文

我们正在开发一个应该执行以下操作的Android应用程序:

  1. 用户安装应用,注册并关闭应用
  2. 一年一次或两次,管理员向包含地理围栏的用户发送优先级较高的Firebase数据邮件
  3. FCM消息启动一个位于电话所在位置的JobService
  4. 如果手机在指定区域内,则会启动“活动”并启动用户互动
  5. 如果手机在该区域之外,则服务停止并且用户永远不会被打扰
  6. 我根据找到here

    的Firebase推送示例开发了应用

    问题

    该应用程序在我的旧手机上工作正常,但在我的新测试手机(Android 8.1.0,LineageOS 15.1)上,当手机处于睡眠模式时,我们遇到了问题。在这种情况下,FCM消息立即到达,但是一旦电话解锁,服务就会首先启动。所以消息卡在2.和3之间。

    我们需要应用程序立即响应 - 而不是在用户决定在2小时后使用手机时。

    我认为问题是由于安装了Android 6的Doze mode。我尝试通过在应用程序中将应用程序添加到白名单中来解决它 - >电池 - >电池优化,但这并没有解决问题问题。

    问题

    1. 打盹模式是否会延迟我的应用程序在2.和3之间?如果是这样,当应用程序在白名单中时为什么没有解决?

    2. 有没有其他方法可以立即启动位置服务? This帖子建议前台服务可以执行此操作,但这需要显示{5}与5分隔。

    3. 除了白名单和前台服务之外,还有其他方法可以立即启动我的服务吗?

3 个答案:

答案 0 :(得分:1)

  

打盹模式是否会延迟我的应用程序在2.和3之间?

documentation打盹模式影响网络访问并阻止JobScheduler

  

如果是这样,当应用程序在白名单中时为什么不能解决?

同样来自documentation:白名单中的应用可以在Doze和App Standby期间使用网络并保留部分唤醒锁。但是,其他限制仍然适用于白名单应用,就像对其他应用一样。

因此阻止JobScheduler仍然适用。

  

有没有其他方法可以立即启动位置服务?这个   post建议前台服务可以做到但这需要   显示的通知以5打破。

忽略电池优化(用于互联网访问)与AlarmManager setAndAllowWhileIdle()setExactAndAllowWhileIdle()一起使用。

小心忽略电池优化

  

Google Play政策禁止应用程序直接豁免Android 6.0+(Doze和App Standby)中的电源管理功能,除非应用程序的核心功能受到不利影响。

我认为这里的一个重要问题是:你真的需要立即执行JobScheduler吗?

  

如果用户将设备拔出并静止一段时间,屏幕关闭,设备将进入打盹模式。

如果设备处于打盹模式,则表示用户未使用它。

  

如果手机在指定区域内,则会启动“活动”并启动用户交互

这是步骤打盹块

  

我们需要应用程序立即响应 - 而不是在用户决定在2小时后使用手机时。

如果设备处于Doze状态,则表示用户未与其进行交互。即使您显示Activity用户未使用手机,他也会在2小时后开始使用手机时看到它:)

答案 1 :(得分:1)

是的!你是对的可能归因于API 23 Marshmallow中引入的Doze and App Standby功能。

正如documentation中所述,系统忽略唤醒锁而系统不允许 JobScheduler运行,这有效阻止您的应用运行作业

一种简单有效的解决方法是在正常 background service内运行位置检测例程,并在收到FCM推送时使用startService()启动它。

请注意,您可能仍然需要 white-list 您的应用,因为正如此处的其他帖子所述,只有列入白名单的应用可以使用网络并保留部分唤醒锁定

答案 2 :(得分:0)

我还没有尝试过, 但您可以使用 WakefulBroadcastReceiver https://developer.android.com/training/scheduling/wakelock.html https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html

根据此链接,您应将接收方声明为:

public class YourReceiver extends WakefulBroadcastReceiver {

可能你的接收器已经是WakefulBroadcastReceiver,因为通知正在显示..

在接收方中,您使用以下命令启动服务(您的服务必须是 IntentService ):

startWakefulService(context, your service);

最后,记得在服务中释放唤醒锁:

@Override
  protected void onHandleIntent(Intent intent) {
      <Your_broadcast_receiver_class>.completeWakefulIntent(intent);
  }

我希望它有所帮助