Android Oreo 在进入待机模式后会杀死后台服务并清除挂起的闹钟和计划任务。

15
我的应用程序有一个后台服务在运行,每五分钟获取用户当前位置并将其更新到服务器。为了持续运行此位置更新过程,我使用闹钟管理器从服务本身设置下一次执行时间。然而,当我在运行Android 8.1的Nokia 6上安装应用程序时,它能够工作一段时间,但如果我让手机空闲一段时间,我的服务将被杀死,并且下一个闹钟也会被清除。我猜测是因为空闲时间使手机进入待机模式。然而,我不明白为什么闹钟管理器会被清除。据我理解,待机模式应该定期打开维护窗口以执行任何未完成的任务。
为了缓解这个问题,我尝试在闹钟管理器之上应用作业调度程序服务,每15分钟运行一次。这个作业调度程序的目的是重新启动具有闹钟管理器的服务,因此即使它被杀死并且闹钟被清除,作业调度程序也会重新启动服务。
在我测试了这个补丁并将其保留一段时间进入空闲模式后,结果是作业调度程序服务和具有闹钟的服务都被杀死,并且计划的作业和闹钟也从系统中清除了。

据Android文档所述,我们可以使用JobScheduler来缓解其后台执行限制。为了测试这一点,我在测试应用程序时强制终止了两个服务,但已经预定的作业并没有被清除,这使得带有警报的服务再次成功运行。我不明白这种行为的原因,尽管Evernote的人在这里Android Job by Evernote给出了一个可能符合这种情况的解释。

对于这种异常行为有什么想法吗?

测试环境详细信息

  • 设备:Nokia 6(TA-1021)
  • 操作系统:Android 8.1.0

你正在运行前台服务还是后台服务?你是否在服务的onDestory()方法中注销AlarmManager? - Sagar
@Sagar 我已经尝试在后台和前台运行了。是的,我正在从作业调度程序服务中注销Alarm。但仅当它已经设置过时才会这样做。运行作业调度程序的目的是清理闹钟管理器并每15分钟重置闹钟。 - k9yosh
@k9yosh,你是否找到了任何解决方案或变通方法来使这在Android Oreo和Oreo+设备中工作?我也遇到了这个问题。 - Qadir Hussain
@QadirHussain 没有,将您的代码移植到基于 FCM 的通知系统是最佳选择。而且它运行得非常流畅。 - k9yosh
@k9yosh谢谢您的回复。您能告诉我这个吗?当接收到推送通知时,我可以注册一个带有ACTION_SCREEN_ON动作的broadcastReciver吗? - Qadir Hussain
@QadirHussain 是的,这应该是可以实现的。 - k9yosh
4个回答

4
在Oreo中,由于行为发生了变化,您将无法长时间运行后台服务,现在,为了优化系统内存、电池等,它会杀死后台服务,为了解决您的问题,您应该使用前台服务。
请参阅《后台执行限制》https://developer.android.com/about/versions/oreo/android-8.0-changes 我的建议是,如果您可以使用FCM,请使用它,因为像微信、Facebook这样的应用程序使用它来传递通知,并且他们没有遇到任何问题...
希望这能帮助您理解这个问题...

我已经尝试使用前台,但仍然被杀掉了。我没有尝试FCM,因为有一些限制。但那似乎是唯一的选择。 - k9yosh
@k9yosh,请查看以下链接,该链接是针对您的任务而设计的: https://developer.android.com/about/versions/oreo/background-location-limits - Abdul Aziz
即使谷歌相册应用被关闭,我一旦点击相机,它仍然会上传照片。这是如何实现的?有任何想法吗? - Durgaprasad
@Durgaprasad 当你点击相机时,它会向谷歌照片发送意图,然后被其捕获,因此开始工作...如果您传递正确的意图并使用意图过滤器捕获它,则可以在任何应用程序中执行此操作。 - Abdul Aziz
这太荒谬了,你需要一个 FCM 服务器才能确保应用程序警报可靠地工作!这是不必要的过度杀伤力...为什么 Android 让开发者的生活如此痛苦?我知道有些不良分子,但你仍然不能随意杀死警报。 - doctorram

1
在Doze模式下,闹钟不会被重置,而是被推迟到稍后的时间。你有两个主要选项:
  1. 使用setAndAllowWhileIdle()setExactAndAllowWhileIdle()。然而,这些也可以以最大频率每9分钟1次触发。因此,你需要减少应用程序获取位置的频率。

  2. 通过显示前台通知来使用前台服务。每个人都这样做(如Uber、Google Maps等应用程序)。这样,你的服务就不会被杀死,并被视为你打开了一个应用程序。


3
我使用了这两个选项,但仍然会被终止。即使是前台服务在待机模式下一段时间后也会被终止。 - k9yosh

0

我目前也遇到了同样的问题,并且像你一样采用了相同的解决方法。也就是将Jobscheduler设置为定期任务,每15分钟启动我的前台服务,以防止出现某些原因(如被杀死的任务)而导致其被终止。这在Oreo版本之前的版本上非常有效。

对于Oreo版本,我目前所知道的唯一解决方案是,在设置中允许应用程序自动启动。在已安装的应用程序下。然后它应该再次像Oreo版本之前那样工作。 据我所听,但尚未测试的是,在Job Scheduler中设置setPersisted(true)选项。 如果有帮助,请告诉我。


是的,你的第一个解决方法适用于Oreo版本之前的版本。我尝试了相反的方法,在其他版本中运行良好,但在Oreo版本中不起作用。我将尝试你的第二个解决方法并回复你。这种行为有什么解释吗? - k9yosh
我已经尝试过setPersisted(true),但在带有Miui的小米Mi Mix2上并没有起作用。但由于他们有自己的方式来处理后台应用程序,这并不一定意味着什么。到目前为止,我唯一的解释是Oreo不允许启动既不被分类为前台也不被分类为后台的应用程序,除非您使用自启动设置明确允许它。不幸的是,我目前还不知道有什么解决方法。 - Al Cabone
我也遇到了同样的问题,有没有解决方案可以管理Doze模式? - Vivek

0

我假设当前的 DOZE 模式不允许后台服务,因此您需要找到一种方式,使得 DOZE 模式不会影响您的应用程序。为了解决您的问题,您应该使用前台服务或进行一些电池设置。无论如何,我更好的建议是您应该选择 Firebase Cloud Messaging


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