Android AlarmManager - RTC_WAKEUP против ELAPSED_REALTIME_WAKEUP - PullRequest
83 голосов
/ 09 мая 2011

Может кто-нибудь объяснить мне разницу между AlarmManager.RTC_WAKEUP и AlarmManager.ELAPSED_REALTIME_WAKEUP? Я прочитал документацию, но до сих пор не понимаю смысла использования одного над другим

Пример кода:

    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 
                     scheduledAlarmTime, 
                     pendingIntent);

    alarmManager.set(AlarmManager.RTC_WAKEUP, 
                     scheduledAlarmTime, 
                     pendingIntent);

Насколько разные две строки кода будут выполняться? Когда эти две строки кода будут выполняться относительно друг друга?

Я ценю вашу помощь.

Ответы [ 5 ]

129 голосов
/ 09 мая 2011

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.

104 голосов
/ 14 марта 2013

Несмотря на принятый в настоящее время и получивший отклик ответ, типы AlarmManager.ELAPSED_REALTIME * вместе с SystemClock.elapsedRealtime () всегда были более надежными, чем часы RTC для сигналов тревоги и времени.

Использование ELAPSED_REALTIME_WAKEUP с AlarmManager будетполагаться на монотонные часы, начинающиеся со времени загрузки ", и продолжает работать, даже когда процессор находится в режимах энергосбережения, поэтому это рекомендуемая основа для общего интервала времени ".Таким образом,

alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()
                 + 60*1000, pendingIntent);

вызовет ваш PendingIntent за 1 минуту (60 * 1000 миллисекунд).

Принимая во внимание, что AlarmManager.RTC_WAKEUP - это стандартное время "стены" в миллисекундах с моментаэпоха.Таким образом,

alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
                 + 60*10000, pendingIntent);

может также вызвать тревогу через 60 секунд, но ненадежно, потому что, как отмечено в документации SystemClock :

Стеначасы могут быть установлены пользователем или телефонной сетью (см. setCurrentTimeMillis (long)), поэтому время может непредсказуемо прыгать назад или вперед.Эти часы следует использовать только тогда, когда важна переписка с реальными датами и временем, например, в приложении с календарем или будильником.Для измерения интервала или истекшего времени следует использовать другие часы.Если вы используете System.currentTimeMillis (), рассмотрите возможность прослушивания трансляций ACTION_TIME_TICK, ACTION_TIME_CHANGED и ACTION_TIMEZONE_CHANGED, чтобы узнать, когда время меняется.

Кроме того, вопрос касается только * _WAKEUP alarсм. также документацию AlarmManager об этом, чтобы убедиться, что вы понимаете, что предоставляют сигналы будильника и не будильника.

17 голосов
/ 25 января 2012

Просто заметка. Вы можете получить время звонка Миллиса:

long uptimeMillis =  SystemClock.elapsedRealtime();

Так что, если вы хотите включить будильник через 30 секунд и хотите использовать часы времени работы вместо обычных часов, вы можете сделать:

long thirtySecondsFromNow =  SystemClock.elapsedRealtime() + 30 * 1000;
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, thirtySecondsFromNow, pendingIntent);

Всякий раз, когда вы хотите проверить, сколько времени прошло, вместо определенной даты / времени, лучше всего использовать время безотказной работы. Это связано с тем, что текущее время, установленное пользователем на устройстве, может измениться, если пользователь изменит его с помощью настроек.

2 голосов
/ 27 апреля 2013

Я запрограммировал эту проблему в своем собственном проекте таким образом. в приведенном ниже коде я использую

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();
    }
}
0 голосов
/ 20 декабря 2016

Некоторые важные примечания, когда выбирает, какой будильник использовать :( для тех, кто уже прочитал голосование против)

RTC_WAKEUP Death Valley - изменение времени:
Если пользователь вручную изменил время на прошлое, будильник не сработает, а в будущем будильник немедленно сработает, если он превысит отметку времени RTC.
Не используйте этот сигнал тревоги для выполнения каких-либо проверок / важных заданий на стороне клиента, поскольку у него есть шанс на сбой.

Значение WAKEUP (Зефир и выше)
В целом - немного.Не будет вызывать устройство, когда idle или в doze, для этого alarmManager.setExactAndAllowWhileIdle или alarmManager.setAndAllowWhileIdle ( Doze & Idle )

...