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

Push message cannot start service at once

上下文

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

  1. 用户安装应用、注册并关闭应用
  2. 管理员每年一次或两次向包含地理围栏的用户发送一条具有高优先级的 Firebase 数据消息
  3. FCM 消息启动一个 JobService,它定位 phone 所在的位置
  4. 如果 phone 在给定区域内,则启动 Activity 并开始用户交互
  5. 如果 phone 在该区域之外,则服务停止并且用户永远不会受到打扰

我根据找到的 Firebase 推送示例开发了应用 here

问题

该应用程序在我的旧 phones 上运行良好,但在我的新测试 phone(android 8.1.0,LineageOS 15.1)中,当 phone 处于睡眠模式。在这种情况下,FCM 消息会立即到达,但服务会在 phone 解锁后首先启动。所以消息卡在 2. 和 3.

之间

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

我假设问题是由于 android 引入的 Doze mode 6. 我试图通过在设置->电池->电池优化中将应用程序添加到白名单来解决它,但是这没有解决问题。

问题

  1. 是打瞌睡模式让我的应用程序在 2. 和 3. 之间延迟吗?如果是为什么应用在白名单中却没有解决?

  2. 有没有其他方法可以一次性启动定位服务? post suggests that a foreground service can do it but this requires that a notification 显示为 5。

  3. 除了白名单和前台服务,还有没有其他方法可以一次性启动我的服务?

我还没试过, 但你可以使用 WakefulBroadcastReceiverhttps://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);
  }

希望对您有所帮助

Is it Doze mode that delays my app between 2. and 3.?

来自 documentation Doze 模式影响网络访问并阻止 JobScheduler

If so why is it not solved when the app is in the whitelist?

同样来自 documentation:列入白名单的应用程序可以使用 网络并在打瞌睡和应用程序待机期间保持部分唤醒锁。但是,其他限制仍然适用于 列入白名单的应用,就像它们对其他应用一样。

所以 JobScheduler 的封锁仍然适用。

Is there any other way to start the location service at once? This post suggests that a foreground service can do it but this requires that a notification is shown which breaks with 5.

忽略电池优化(用于 Internet 访问)结合 AlarmManagersetAndAllowWhileIdle()setExactAndAllowWhileIdle() 应该有效。

小心忽略电池优化

Google Play policies prohibit apps from requesting direct exemption from Power Management features in Android 6.0+ (Doze and App Standby) unless the core function of the app is adversely affected.

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

If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode.

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

if the phone is inside the given area an Activity is started and user interaction starts

这是打瞌睡块的步骤

We need the app to respond at once - not when the user decides to use his phone 2 hours later.

如果设备处于打瞌睡状态,则表示用户未与其交互。即使你显示 Activity 用户没有使用 phone,他会在 2 小时后开始使用它时看到它:)

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

documentation 中所述,系统 忽略唤醒锁 并且系统 不允许 JobScheduler 到 运行,这有效地阻止了您的应用程序 运行job.

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

请注意,您可能仍然需要white-list您的应用,因为正如另一个post中提到的, 只有列入白名单的应用程序才能使用网络并持有部分唤醒锁。