推送消息无法一次启动服务



>上下文

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

  1. 用户安装应用、注册并关闭应用
  2. 管理员每年向包含地理围栏的用户发送一次优先级较高的 Firebase 数据消息
  3. FCM 消息启动一个作业服务,用于定位电话所在的位置
  4. 如果手机在给定区域内,则启动活动并开始用户交互
  5. 如果电话在该区域之外,则服务将停止,用户永远不会受到干扰

我根据此处的 Firebase 推送示例开发了该应用程序

问题所在

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

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

我认为问题是由于 android 6 引入的打瞌睡模式造成的。我试图通过将应用程序添加到设置>电池>电池优化中的白名单来解决这个问题,但这并没有解决问题。

问题

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

  2. 有没有其他方法可以一次启动定位服务?这篇文章建议前台服务可以做到这一点,但这需要显示一个通知,该通知中断了 5。

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

是的!你是对的,这可能是由于API 23 Marshmallow中引入的打瞌睡和应用程序待机功能。

如文档中所述,系统会忽略唤醒锁,并且系统不允许运行JobScheduler,这有效地阻止了应用运行作业

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

请注意,您可能仍需要将您的应用列入白名单,因为正如此处另一篇文章所述,只有列入白名单的应用才能使用网络并保持部分唤醒锁定。

是打瞌睡模式将我的应用程序延迟到 2. 和 3 之间吗?

从文档中 打瞌睡模式影响网络访问并阻止JobScheduler

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

同样来自文档:列入白名单的应用程序可以使用网络,并在低电耗模式和应用程序待机期间保持部分唤醒锁定。但是,其他限制仍然适用于列入白名单的应用,就像它们适用于其他应用一样。

因此,JobScheduler的阻止仍然适用。

有没有其他方法可以一次启动定位服务?这 Post建议前台服务可以做到这一点,但这需要 显示一个通知,其中中断了 5。

忽略电池优化(用于互联网访问)与具有setAndAllowWhileIdle()setExactAndAllowWhileIdle()AlarmManager结合使用应该可以工作。

小心忽略电池优化

Google Play 政策禁止应用申请直接免除 Android 6.0+ 中的电源管理功能(低电耗模式和应用待机功能),除非应用的核心功能受到不利影响。

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

如果用户将设备

拔下并静止一段时间,在屏幕关闭的情况下,设备将进入低电耗模式。

如果设备处于低电耗模式,则表示用户未使用它。

如果手机在给定区域内,则启动活动并开始用户交互

这是打瞌睡块的步骤

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

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

我仍然没有尝试, 但您可以使用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);
}

我希望它有所帮助

相关内容

  • 没有找到相关文章

最新更新