一些设备上,当应用关闭时,Android AlarmManager无法正常工作

32

我试图通过AlarmManagersetRepeating()方法每半小时运行IntentService。我想从广播发送信息到服务中,然后在服务中执行一些功能。

但是,在应用程序关闭状态下,初始的AlarmManager没有触发。

当我的应用程序正在运行或在后台状态时,闹钟正常工作,但是有一些设备闹钟在关闭应用程序后无法正常工作。

我应该怎么做才能让闹钟即使在应用程序关闭后也能正常运行?


5
请注意,用户13的答案绝对正确,但是一些设备(例如华为)也会实现自己的能源管理,你不能通过编程摆脱它。在我的华为Ascend Mate 7上,无论我做什么(根据开发者指南对待Doze模式的建议),都不起作用。相反,我必须手动进行一些设备设置,这只能手动完成... - Opiatefuchs
@Opiatefuchs:你能详细说明一下吗?(在我的LTE刀片上,即使手动警告和省电模式设置也没有帮助,但也许还有其他方法?) - serv-inc
2
@serv-inc:嗯,这很难说,因为有很多不同的实现方式。我希望将来会变得独一无二,或者更好地解释和更加用户友好。在华为手机上,也有自启动设置。我在“电话管理器”中找到了这些设置。 - Opiatefuchs
5个回答

39

根据setRepeating()的文档:

从API 19开始,所有重复警报都是不精确的。

此外,setRepeating()不能与Doze模式一起使用。

您应该使用准确的警报(根据设备的API级别设置适当的AlarmManager方法):

if (Build.VERSION.SDK_INT >= 23) {
    alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
            triggerTime, pendingIntent);
} else if (Build.VERSION.SDK_INT >= 19) {
    alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
} else {
    alarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
}

重新安排每次触发时间。

对于重新安排,您可以将原始触发时间添加到Intent中:

intent.putExtra(KEY_TRIGGER_TIME, triggerTime);

然后在 onReceive() 中检索这个额外的内容,将您想要的间隔添加到其中,并使用新值重新安排闹钟:

然后在onReceive()中检索此额外内容,添加您所需的时间间隔,并使用新值重新安排警报:

(Two possible translations depending on context, please choose the appropriate one.)
@Override
public void onReceive(Context context, Intent intent) {
    long triggerTime = intent
            .getLongExtra(KEY_TRIGGER_TIME, System.currentTimeMillis());

    // adding one day to the current trigger time
    triggerTime += TimeUnit.DAYS.toMillis(1);

    // set a new alarm using the new trigger time
    // ...
}
< p > < em > 注意: 如上方评论中@Opiatefuchs所提到的,一些制造商(如小米或华为)可能会实现某些电池节省功能,这些功能可以防止闹钟被触发,并且无法通过编程方式绕过。


5
为什么?亲爱的制造商们,你们的手机被广泛使用/销售是因为我们的努力而非你们应用程序被用户使用,而你们让我们难以应对这种情况。如果谷歌不对制造商施加的这些愚蠢限制采取任何行动,那么我们很快就会转向苹果生态系统。 - Sai
即使我在接收器中加上一个,但循环仍从警报开始,为什么?例如通知一遍又一遍地重复。 - Attaullah
1
@Sai 我完全同意,我一直都说过这个问题。这些制造商为了自己的利益而进行大量更改,不关心开发人员所付出的辛勤劳动,他们必须为每一个小问题寻找解决方案。Google 对这些做法并不十分谨慎,每次我处理调度通知时都感到非常厌烦。 - Taki

18

现在的设备在电池功耗方面越来越注重安全性。默认情况下,设备会将几乎所有应用程序置于省电模式下。这意味着对于某些设备,当您退出应用程序时,后台工作(位置、闹钟管理)将不起作用。在其他设备上,当电池电量达到阈值(例如13%)时,后台任务将停止工作。因此,即使在后台运行,您需要将您的应用程序从这种省电模式中排除以使其顺畅运行。在这两个制造商中实现该行为的方法是:

Xiaomi

  • 进入“电池” => “省电” => “应用程序电池优化器” => 选择您的应用程序并选择“无限制”(关于后台设置),然后允许“后台位置”选项。

  • 要在启动后自动启动您的应用程序:转到“安全”应用程序 => “权限” => “自动启动”并勾选您的应用程序。

Samsung

三星智能管理应用程序在3天内如果您不使用应用程序,则停止所有后台工作。因此,禁用此功能的方法如下:

  • 在“设置”中进入“电池” => “未监视的应用程序” => 将您的应用程序添加到白名单中。其他一些三星版本禁用此功能的位置可能会有所不同,例如“电池” => “详细信息” => 选择应用程序并选择“不优化”。

对于其他设备,应该有相同的电源选项,可以直接在设置选项中或通过某些应用程序进行处理。


2
那么,有没有办法绕过这个问题,我是说即使应用程序正在进行优化时?那么,安卓默认的闹钟应用程序是如何工作的? - Noor Hossain

6

首先,Android Studio存在一个bug。如果你从Android Studio启动应用程序,然后从最近的应用中滑出该应用程序,闹钟将被删除。因此,在这种情况下,请通过点击启动器图标重新启动您的应用程序。如果您再次将其滑出时,闹钟仍将存在。

其次,在某些带有电池优化功能的设备上,您应该启动前台服务,并且它完全正常工作。

我使用这两个要点使其正常运行,现在它可以运行得很好。


我也遇到了同样的问题。在我的情况下,我停止了应用程序的电池优化,但在关闭应用程序后,似乎它根本无法触发我的广播接收器。请分享您对此情况的想法。我在Pixel 4XL操作系统:11中遇到了这个问题。 - fahad_sust
谢谢!我注意到了你描述的确切错误行为,这让我很疯狂。我以为我的代码有问题,但现在它有意义了。 - Lifes

4
以下行为在充满电后发生了变化。先前,在禁用此应用程序的节能功能后,它会显示没有启用任何节能等,但只有在充满电(从非常低的电量状态)后设备才会表现出应有的行为。因此,请更改该应用程序的设置,然后进行完全充电(可能仅在之前电池电量较低时)。这可能会解决问题。

ZTE Blade L110

即使关闭了电池节省模式(设置 -> 电池 -> 选项 -> 电池节省),并将应用程序标记为重要的消息(设置 -> 提示和通知 -> 应用程序通知 -> 应用名称 -> 优先级),似乎 setExactsetAlarmClock 都没有按时触发。


3

对于联想手机:

您需要进入设置 -> 应用程序 -> 选择应用程序 -> 取消选中限制启动

现在它将以被杀状态在后台运行。


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