有人可以向我解释AlarmManager.RTC_WAKEUP
和AlarmManager.ELAPSED_REALTIME_WAKEUP
之间的区别吗?我已经阅读了文档,但仍然没有真正理解使用其中一个的含义。
示例代码:
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
scheduledAlarmTime,
pendingIntent);
alarmManager.set(AlarmManager.RTC_WAKEUP,
scheduledAlarmTime,
pendingIntent);
这两行代码的执行方式有多么不同?这两行代码何时相对于彼此执行?
感谢您的帮助。
答案 0 :(得分:128)
AlarmManager.ELAPSED_REALTIME_WAKEUP
类型用于在启动时触发警报:
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 600000, pendingIntent);
实际上会在设备启动后 10分钟后关闭闹钟。
当设备启动时,有一个计时器开始运行以测量设备的正常运行时间,这是根据设备的正常运行时间触发警报的类型。
然而,AlarmManager.RTC_WAKEUP
将根据时钟的时间触发警报。例如,如果你这样做:
long thirtySecondsFromNow = System.currentTimeMillis() + 30 * 1000;
alarmManager.set(AlarmManager.RTC_WAKEUP, thirtySecondsFromNow , pendingIntent);
另一方面,这将从现在开始 30秒后触发警报。
与AlarmManager.ELAPSED_REALTIME_WAKEUP
相比,很少使用 AlarmManager.RTC_WAKEUP
类型。
答案 1 :(得分:103)
尽管目前已接受并已投票,但AlarmManager.ELAPSED_REALTIME *类型以及SystemClock.elapsedRealtime()始终比报警和计时的RTC时钟更可靠。
对于AlarmManager使用ELAPSED_REALTIME_WAKEUP将依赖于从启动时间“开始的单调时钟,并且即使在CPU处于省电模式时也会继续打勾,因此通用间隔时间的推荐基础” 。所以,
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()
+ 60*1000, pendingIntent);
将在1分钟内(60 * 1000毫秒)激活你的PendingIntent。
然而,AlarmManager.RTC_WAKEUP用于自纪元以来的标准“墙”时间(以毫秒为单位)。所以,
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+ 60*10000, pendingIntent);
也可能在60秒后触发警报,但不可靠,因为SystemClock documentation中已提到:
挂钟可由用户或电话网络设置(请参阅 setCurrentTimeMillis(long)),所以时间可能会向后跳跃或 不可预测地转发。这个时钟只应在使用时使用 与现实日期和时间的对应很重要,例如 在日历或闹钟应用程序中。间隔或经过的时间 测量应使用不同的时钟。如果你正在使用 System.currentTimeMillis(),考虑听 ACTION_TIME_TICK,ACTION_TIME_CHANGED和ACTION_TIMEZONE_CHANGED 意图广播以找出时间的变化。
此外,该问题仅引用了* _WAKEUP警报,但另请参阅AlarmManager文档,以确保您了解唤醒与非唤醒警报提供的内容。
答案 2 :(得分:16)
请注意。您可以通过以下方式获得正常运行时间:
long uptimeMillis = SystemClock.elapsedRealtime();
因此,如果您想在30秒后触发警报,并且您想使用正常运行时钟而不是正常时钟,则可以执行以下操作:
long thirtySecondsFromNow = SystemClock.elapsedRealtime() + 30 * 1000;
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, thirtySecondsFromNow, pendingIntent);
每当您想要检查一些经过的时间而不是特定的日期/时间时,最好使用正常运行时间。这是因为如果用户使用设置更改设备,用户在设备中设置的当前时间可能会发生变化。
答案 3 :(得分:2)
我用这种方式在我自己的项目中编写了这个问题。在下面的代码我正在使用
AlarmManager.ELAPSED_REALTIME_WAKEUP
在特定时间设置闹钟。 变量'intentName'在intentFilter中用于接收此警报。因为我发射了许多此类警报。当我取消所有闹钟。我使用取消方法。在底部给出。
//保持警报并在需要时取消
public static ArrayList<String> alarmIntens = new ArrayList<String>();
//
public static String setAlarm(int hour, int minutes, long repeatInterval,
final Context c) {
/*
* to use elapsed realTime monotonic clock, and fire alarm at a specific time
* we need to know the span between current time and the time of alarm.
* then we can add this span to 'elapsedRealTime' to fire the alarm at that time
* this way we can get alarms even when device is in sleep mood
*/
Time nowTime = new Time();
nowTime.setToNow();
Time startTime = new Time(nowTime);
startTime.hour = hour;
startTime.minute = minutes;
//get the span from current time to alarm time 'startTime'
long spanToStart = TimeUtils.spanInMillis(nowTime, startTime);
//
intentName = "AlarmBroadcast_" + nowTime.toString();
Intent intent = new Intent(intentName);
alarmIntens.add(intentName);
PendingIntent pi = PendingIntent.getBroadcast(c, alarms++, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
//
AlarmManager am = (AlarmManager) c
.getSystemService(Context.ALARM_SERVICE);
//adding span to elapsedRealTime
long elapsedRealTime = SystemClock.elapsedRealtime();
Time t1 = new Time();
t1.set(elapsedRealTime);
t1.second=0;//cut inexact timings, seconds etc
elapsedRealTime = t1.toMillis(true);
if (!(repeatInterval == -1))
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
elapsedRealTime + spanToStart, repeatInterval, pi);
else
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, elapsedRealTime
+ spanToStart, pi);
其中span函数是这样的:
public static long spanInMillis(Time startTime, Time endTime) {
long diff = endTime.toMillis(true) - startTime.toMillis(true);
if (diff >= 0)
return diff;
else
return AlarmManager.INTERVAL_DAY - Math.abs(diff);
}
报警取消功能就是这个。
public static void cancel(Context c) {
AlarmManager am = (AlarmManager) c
.getSystemService(Context.ALARM_SERVICE);
// cancel all alarms
for (Iterator<String> iterator = alarmIntens.iterator(); iterator
.hasNext();) {
String intentName = (String) iterator.next();
// cancel
Intent intent = new Intent(intentName);
PendingIntent pi = PendingIntent.getBroadcast(c, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
//
iterator.remove();
}
}
答案 4 :(得分:0)
choosing which alarm to use时的一些重要说明:(对于已经阅读过投票的人而言)
RTC_WAKEUP
死亡谷 - 时间变化:
如果用户手动将时间更改为过去,则警报将不会响起,并且如果警报超过RTC
时间戳,将来会立即关闭警报。
不要使用此警报执行任何客户端验证/重要作业,因为它有可能失败。
WAKEUP
含义(棉花糖及以上)
一般来说 - 并不多。在idle
或doze
内,alarmManager.setExactAndAllowWhileIdle
或alarmManager.setAndAllowWhileIdle
(Doze & Idle)