【问题标题】:Alarm Manager issue in Android 6.0 Doze modeAndroid 6.0 打盹模式中的警报管理器问题
【发布时间】:2016-02-25 13:54:04
【问题描述】:

我制作了一个在 Android 6.0 之前一直可用的应用。我认为这是打盹功能,它不允许我的闹钟触发。

我使用 sharedpreferences 来处理选项:

//ENABLE NIGHT MODE TIMER
    int sHour = blockerTimerPreferences.getInt("sHour", 00);
    int sMinute = blockerTimerPreferences.getInt("sMinute", 00);

    Calendar sTime = Calendar.getInstance();
    sTime.set(Calendar.HOUR_OF_DAY, sHour);
    sTime.set(Calendar.MINUTE, sMinute);

    Intent enableTimer = new Intent(context, CallReceiver.class);
    enableTimer.putExtra("activate", true);
    PendingIntent startingTimer = PendingIntent.getBroadcast(context, 11002233, enableTimer, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager sAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    sAlarm.setRepeating(AlarmManager.RTC_WAKEUP,
            sTime.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, startingTimer);

这里有什么问题的线索吗?

这是一个阻止来电的应用程序。谢谢!

编辑: 我有 3 个文件(更多但...),例如:

MainActivity (All code)
CallReceiver (Broadcast that triggers the alarm again (reboot etc))
CallReceiverService (Handles the call / phone state)

【问题讨论】:

  • 使用adb shell dumpsys alarm 确认您的闹钟已安排。请注意,setRepeating() 在 Android 4.4+ 上是不准确的。 “这也会导致电池耗尽”——这似乎不太可能。不运行的代码不应该消耗电池。
  • 嗨@CommonsWare,52 次唤醒和 52 次警报......它总是在发出警报。 setRepeating() 会在那一刻触发,我认为没问题。
  • @FilipeOS 你成功了吗?我们可以在打盹模式下实现alarmManager.setRepeating()吗?
  • @devgeek 只像这样并创建一个服务来检查启动等。 setExactAndAllowWhileIdle on >M 和旧版本 setExact
  • setExact 不会重复。如果我需要让它重复怎么办? @FilipeOS

标签: android alarmmanager android-pendingintent android-alarms android-doze-and-standby


【解决方案1】:

打盹模式会将您的警报延迟到下一个维护时段。为避免Doze mode 阻止您的闹钟,您可以使用setAndAllowWhileIdle()setExactAndAllowWhileIdle()setAlarmClock()。您将有大约 10 秒的时间来执行您的代码,并设置您的下一个警报(不过对于使用 _AndAllowWhileIdle 的方法,每 15 分钟不超过一次)

如果你想测试打盹模式,可以使用ADB command

  1. 使用 Android 6.0(API 级别 23)或更高系统映像配置硬件设备或虚拟设备。

  2. 将设备连接到您的开发机器并安装您的应用。

  3. 运行您的应用并使其保持活动状态。
  4. 关闭设备屏幕。 (该应用程序保持活动状态。) 通过运行以下命令强制系统在打盹模式中循环:

    adb shell dumpsys battery unplug

    adb shell dumpsys deviceidle step

  5. 您可能需要多次运行第二个命令。重复此操作,直到设备状态变为空闲。

  6. 在重新激活设备后观察应用程序的行为。确保应用在设备退出 Doze 时正常恢复。

编辑:添加 setAlarmClock 示例

别忘了检查 SDK 级别 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, MyAlarmReceiver.class); //or just new Intent() for implicit intent 
//set action to know this come from the alarm clock
intent.setAction("from.alarm.clock");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//Alarm fire in 5s.
am.setAlarmClock(new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + 5000, pi), pi);

【讨论】:

  • 嗨@xiaomi,只需将setRepeating 替换为setAlarmClock?使用相同的参数?你能举个例子吗?谢谢!
  • 我编辑了我的答案,但这与其他设置警报方法并没有太大区别。
  • 这只是一个在 5 秒后发出警报的例子。选择您想要的时间。
  • 嗨@xiaomi,那个intent.setAction("from.alarm.clock");在我的手机上显示了闹钟图标,如果我删除了,有什么问题吗?
  • 啊,我没有看到 setAlarmClock 会将时钟图标带入状态栏。顺便说一句,设置操作仅适用于您检查接收者 intent.getAction()。要删除图标,您必须使用 setAlarmClock() 之外的其他方法
【解决方案2】:

如果设备处于打盹模式,您需要使用以下 API 之一: setExactAndAllowWhileIdlesetAndAllowWhileIdle.

请注意,在打瞌睡模式下没有用于唤醒设备的 API 用于重复警报,因此如果您需要在打瞌睡时使用重复警报来唤醒设备,您必须使用上述 API 并重新启用每次计时器触发时的计时器。

【讨论】:

    猜你喜欢
    • 2017-12-18
    • 2015-12-06
    • 2017-04-25
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多