2011-05-09 21 views
73

¿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 la implicación de usar uno sobre el otro.Android AlarmManager - RTC_WAKEUP vs ELAPSED_REALTIME_WAKEUP

código Ejemplo:

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

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

Cómo diferente, las dos líneas de código ejecutar? ¿Cuándo se ejecutarán esas dos líneas de código en relación el uno con el otro?

Agradezco su ayuda.

Respuesta

117

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

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

realmente hacer que la alarma se activa 10 minutos después se inicia el dispositivo.

Hay un temporizador que se inicia cuando el dispositivo se inicia para medir el tiempo de actividad del dispositivo y este es el tipo que activa su alarma de acuerdo con el tiempo de actividad del dispositivo.

Considerando que, AlarmManager.RTC_WAKEUP disparará la alarma de acuerdo con la hora del reloj. Por ejemplo si lo hace:

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

esto, por el contrario, se activará la alarma 30 segundos a partir de ahora.

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

+1

Eso es lo que pensaba. Solo necesitaba una confirmación. Entonces, si hice algo como esto: alarmManager.set (AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMills() + 30 * 1000, pendingIntent); cosas extrañas que podría suceder (que es lo que tenía hasta que me di cuenta de que no estaba funcionando como pensé. –

+2

Tenga en cuenta que el código debería ser 'System.currentTimeMillis()' en lugar de 'System.currentTimeMills()' :) – HasanAboShally

+11

"El tipo AlarmManager.ELAPSED_REALTIME_WAKEUP rara vez se usa en comparación con AlarmManager.RTC_WAKEUP". Esto es especulación y malos consejos. De acuerdo con la documentación: https://developer.android.com/training/scheduling/alarms.html "Si simplemente necesita que su alarma se dispare en un intervalo particular (por ejemplo, cada media hora), use uno de los tipos de tiempo real transcurridos. En general, esta es la mejor opción ". –

15

Solo una nota. Usted puede obtener el llamado tiempo de actividad millis:

long uptimeMillis = SystemClock.elapsedRealtime(); 

Así que si quieres para disparar la alarma de 30 segundos a partir de ahora, y desea usar el reloj de tiempo de actividad en lugar de la normal de reloj, que puede hacer:

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

Cuando quiera verificar el tiempo transcurrido en lugar de una fecha/hora específica, es mejor utilizar 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 la configuración.

+3

+1 para indicar que se usa "siempre que desee verificar el tiempo transcurrido". Perfectamente tiene sentido. – sulai

+0

Nuevamente solo para estresar: mi entendimiento es que esto definitivamente disparará dentro de 30 segundos a menos que ocurra algo así como que el dispositivo se apague. Concretamente, creo que el problema con el uso de RTC_WAKEUP es que, en teoría, en 15 segundos a partir de ahora, es posible que sea algo así como 1am un sábado cerca de fines de octubre y el reloj del sistema se remonta 1 hora (en EE. UU. Europa, al menos), entonces la alarma no se dispara hasta 1 hora y 30 segundos después de que se configuró. – Yannick

92

A pesar de la respuesta actualmente aceptada y votada arriba, AlarmManager.ELAPSED_REALTIME * tipos junto con SystemClock.elapsedRealtime() siempre ha sido más fiable que los relojes de RTC para las alarmas y el tiempo.

Usando ELAPSED_REALTIME_WAKEUP con AlarmManager se basará en un reloj monótona partir de tiempo de inicio "y continúa a marcar incluso cuando la CPU está en modo de ahorro de energía, por lo que es la base para recomendar propósito general tiempo de intervalo". Así,

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

hará que su fuego PendingIntent en 1 min (60 * 1000 milisegundos).

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

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

también puede activar la alarma de 60 segundos a partir de ahora, pero no de forma fiable, ya que como se ha señalado en el SystemClock documentation:

El reloj de pared se puede configurar por el usuario o la red de telefonía (ver setCurrentTimeMillis (long)), por lo que el tiempo puede saltar hacia atrás o reenvía impredeciblemente. Este reloj solo debe utilizarse cuando la correspondencia con las fechas y horas del mundo real es importante, como en una aplicación de calendario o reloj despertador. Las mediciones de intervalo o tiempo transcurrido deben usar un reloj diferente. Si está utilizando System.currentTimeMillis(), piense en escuchar a los ACTION_TIME_TICK, ACTION_TIME_CHANGED y ACTION_TIMEZONE_CHANGED emisiones de intención para averiguar cuándo los cambios de tiempo.

Además, la cuestión sólo se hace referencia sólo las alarmas * _WAKEUP pero ver también la documentación AlarmManager en que para asegurarse de que entiende lo que el despertar frente a las alarmas de activación no proporcionan.

+0

Su respuesta es excelente, pero en mi aplicación, necesitaba establecer alarmas que coincidieran con la fecha/hora del mundo real y no solo con 60 segundos a partir de ahora. En ese caso, RTC_WAKEUP es la mejor solución para mí. –

+7

Eso está bien, pero esta es una respuesta más precisa a la pregunta y corrige las cosas en la respuesta actualmente aceptada. – mborsuk

+0

+1 para esta información, pero tenga en cuenta que 'elapsedRealtime()' está en 'SystemClock' en lugar de' System'. EDITAR: ... Límite de votación diaria alcanzado ... –

2

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

AlarmManager.ELAPSED_REALTIME_WAKEUP 

para configurar la alarma en un momento específico. la variable 'intentName' se usa en el intentFilter para recibir esta alarma. porque estoy disparando muchas alarmas de este tipo. cuando cancelo todas las alarmas utilizo el método cancelar. dado en la parte inferior.

// para mantener las alarmas y cancelar 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 palmo es la siguiente:

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

alarma cancelar la función es la siguiente.

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

Algunas notas importantes a la hora choosing which alarm to use: (para quienes que ya leyó los votos upvoted)

ElRTC_WAKEUPValle de la Muerte - cambio de hora:
Si el usuario ha cambiar manualmente el tiempo para En el pasado, la alarma no se activará y, en el futuro, la alarma se activará inmediatamente si supera la marca de tiempo RTC.
No use use esta alarma para hacer cualquier verificación del lado del cliente/trabajos importantes porque puede fallar.

El significadoWAKEUP(malvavisco y superior)
En general - no mucho.no despertarè el dispositivo cuando idle o mientras que en doze, para que alarmManager.setExactAndAllowWhileIdle o alarmManager.setAndAllowWhileIdle (Doze & Idle)

Cuestiones relacionadas