47 votos

Android AlarmManager - RTC_WAKEUP vs ELAPSED_REALTIME_WAKEUP

¿Puede alguien explicarme la diferencia entre AlarmManager.RTC_WAKEUP y AlarmManager.ELAPSED_REALTIME_WAKEUP ? He leído la documentación pero todavía no entiendo realmente la implicación de usar uno sobre el otro.

Ejemplo de código:

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

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

¿Qué tan diferentes serán las dos líneas de código que se ejecutarán? ¿Cuándo se ejecutarán esas dos líneas de código en relación con cada una de ellas?

Aprecio su ayuda.

73voto

Rejinderi Puntos 3584

AlarmManager.ELAPSED_REALTIME_WAKEUP se utiliza para activar la alarma desde el momento del arranque:

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

hará que suene la alarma 10 min. después de que el dispositivo arranque .

Hay un temporizador que comienza a funcionar cuando el dispositivo se enciende para medir el tiempo de funcionamiento del dispositivo y este es el tipo que activa su alarma de acuerdo con el tiempo de funcionamiento del dispositivo.

Considerando que, AlarmManager.RTC_WAKEUP disparará la alarma según la hora del reloj. Por ejemplo, si lo haces:

int thirtySecondsFromNow = System.currentTimeMillis() + 30 * 1000;
alarmManager.set(AlarmManager.RTC_WAKEUP, thirtySecondsFromNow , pendingIntent);

esto, por otro lado, activará la alarma Dentro de 30 segundos .

AlarmManager.ELAPSED_REALTIME_WAKEUP tipo se utiliza raramente en comparación con AlarmManager.RTC_WAKEUP .

67voto

mborsuk Puntos 476

A pesar de la respuesta actualmente aceptada y votada, los tipos AlarmManager.ELAPSED_REALTIME* junto con SystemClock.elapsedRealtime() siempre han sido más fiables que los relojes RTC para las alarmas y la sincronización.

Usando ELAPSED_REALTIME_WAKEUP con AlarmManager dependerá de un reloj monótono a partir del tiempo de arranque " y sigue funcionando incluso cuando la CPU está en modo de ahorro de energía, así que es la base recomendada para la sincronización de intervalos de propósito general ". Así que..,

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

hará que tu PendingIntent se dispare en 1 min (60*1000 milisegundos).

Mientras que, AlarmManager.RTC_WAKEUP es para el tiempo estándar de "pared" en milisegundos desde la época. Así que,

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

también puede disparar la alarma dentro de 60 segundos, pero no de forma fiable, porque como se indica en la Documentación de SystemClock :

El reloj de pared puede ser configurado por el usuario o por la red telefónica (véase setCurrentTimeMillis(long)), así que el tiempo puede saltar hacia atrás o avanza de forma impredecible. Este reloj sólo debe ser usado cuando la correspondencia con las fechas y horas del mundo real es importante, como en una aplicación de calendario o despertador. Intervalo o tiempo transcurrido las mediciones deben usar un reloj diferente. Si está usando System.currentTimeMillis(), considere escuchar el TIEMPO DE ACCIÓN, CAMBIO DE TIEMPO DE ACCIÓN y CAMBIO DE ZONA DE TIEMPO DE ACCIÓN Emisiones de intención para saber cuándo cambia el tiempo.

Además, la pregunta sólo se refería a las alarmas *_WAKEUP pero también a las AlarmManager documentación sobre eso para asegurarse de que entiendes lo que proporcionan las alarmas de despertador vs. no despertador.

11voto

Ena Puntos 797

Sólo una nota. Puedes obtener el tiempo de actividad de Millis llamando:

long uptimeMillis =  SystemClock.elapsedRealtime();

Así que si quieres disparar la alarma dentro de 30 segundos, y quieres usar el reloj de tiempo de actividad en lugar del reloj normal, puedes hacerlo:

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

Siempre que quieras comprobar el tiempo transcurrido en lugar de una fecha/hora específica, es mejor usar el tiempo de actividad. Esto se debe a que la hora actual establecida por el usuario en el dispositivo puede cambiar si el usuario la cambia usando los ajustes.

2voto

ahmadalibaloch Puntos 194

Programé este problema en mi propio proyecto de esta manera. En el código de abajo estoy usando

AlarmManager.ELAPSED_REALTIME_WAKEUP

para poner la alarma a una hora específica. La variable "nombre de la intención" se usa en el filtro de intención para recibir esta alarma. Porque estoy disparando muchas alarmas de este tipo. Cuando cancelo todas las alarmas, uso el método de cancelación que se da en la parte inferior.

//para mantener las alarmas y cancelarlas cuando sea necesario.

     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);

donde la función span es esta:

 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);
}

La función de cancelación de la alarma es esta.

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();
    }
}

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X