Android 6.0 Doze 模式中的警报管理器问题
Alarm Manager issue in Android 6.0 Doze mode
我制作了一个在 Android 6.0 之前一直有效的应用程序。我认为是 Doze 功能不允许我的闹钟触发。
我使用 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)
如果设备处于打瞌睡模式,您需要使用其中之一 API:
setExactAndAllowWhileIdle 或
setAndAllowWhileIdle.
请注意,没有 API 可以在重复闹钟的打瞌睡模式下唤醒设备,因此如果您需要重复闹钟来在打瞌睡时唤醒设备,您必须使用 APIs 并在每次触发定时器时重新启动定时器。
打瞌睡模式会将您的警报延迟到下一次维护 window。避免了Doze mode to block your alarm, you can use setAndAllowWhileIdle()
, setExactAndAllowWhileIdle()
or setAlarmClock()
。您将有大约 10 秒的时间来执行您的代码,并设置您的下一个警报(但是对于 _AndAllowWhileIdle
的方法每 15 分钟不超过一次)
如果你想测试Doze模式,你可以使用ADB command:
Configure a hardware device or virtual device with an Android 6.0 (API level 23) or higher system image.
Connect the device to your development machine and install your app.
- Run your app and leave it active.
Shut off the device screen. (The app remains active.)
Force the system to cycle through Doze modes by running the following commands:
adb shell dumpsys battery unplug
adb shell dumpsys deviceidle step
You may need to run the second command more than once. Repeat it until the device state changes to idle.
- Observe the behavior of your app after you reactivate the device. Make sure the app recovers gracefully when the device exits 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);
我制作了一个在 Android 6.0 之前一直有效的应用程序。我认为是 Doze 功能不允许我的闹钟触发。
我使用 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)
如果设备处于打瞌睡模式,您需要使用其中之一 API: setExactAndAllowWhileIdle 或 setAndAllowWhileIdle.
请注意,没有 API 可以在重复闹钟的打瞌睡模式下唤醒设备,因此如果您需要重复闹钟来在打瞌睡时唤醒设备,您必须使用 APIs 并在每次触发定时器时重新启动定时器。
打瞌睡模式会将您的警报延迟到下一次维护 window。避免了Doze mode to block your alarm, you can use setAndAllowWhileIdle()
, setExactAndAllowWhileIdle()
or setAlarmClock()
。您将有大约 10 秒的时间来执行您的代码,并设置您的下一个警报(但是对于 _AndAllowWhileIdle
的方法每 15 分钟不超过一次)
如果你想测试Doze模式,你可以使用ADB command:
Configure a hardware device or virtual device with an Android 6.0 (API level 23) or higher system image.
Connect the device to your development machine and install your app.
- Run your app and leave it active.
Shut off the device screen. (The app remains active.) Force the system to cycle through Doze modes by running the following commands:
adb shell dumpsys battery unplug
adb shell dumpsys deviceidle step
You may need to run the second command more than once. Repeat it until the device state changes to idle.
- Observe the behavior of your app after you reactivate the device. Make sure the app recovers gracefully when the device exits 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);