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 la implicación de usar uno sobre el otro.

Código de ejemplo:

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

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

Aprecio tu ayuda.

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

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

hará que la alarma suene 10 minutos después de que el dispositivo se inicie .

Hay un temporizador que se inicia cuando el dispositivo arranca 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.

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

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

esto, por otro lado, disparará la alarma dentro de 30 segundos .

AlarmManager.ELAPSED_REALTIME_WAKEUP tipo AlarmManager.ELAPSED_REALTIME_WAKEUP rara vez se usa en comparación con AlarmManager.RTC_WAKEUP .

A pesar de la respuesta actualmente aceptada y actualizada, los tipos AlarmManager.ELAPSED_REALTIME * junto con SystemClock.elapsedRealtime () siempre han sido más confiables que los relojes RTC para alarmas y tiempos.

El uso de ELAPSED_REALTIME_WAKEUP con AlarmManager dependerá de un reloj monotónico que comience desde el tiempo de arranque ” y continúa marcando incluso cuando la CPU está en modo de ahorro de energía, por lo que es la base recomendada para la temporización de intervalo de propósito general “. Asi que,

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

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

Mientras que, AlarmManager.RTC_WAKEUP es para el tiempo estándar de “pared” en milisegundos desde la época. Asi que,

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

también puede activar la alarma 60 segundos a partir de ahora, pero no de manera confiable, porque como se indica en la documentación de SystemClock :

El reloj de pared puede ser configurado por el usuario o la red del teléfono (ver setCurrentTimeMillis (long)), por lo que el tiempo puede saltar hacia atrás o hacia adelante de manera impredecible. 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 (), considere escuchar las transmisiones de ACTION_TIME_TICK, ACTION_TIME_CHANGED y ACTION_TIMEZONE_CHANGED Intent para averiguar cuándo cambia la hora.

Además, la pregunta solo hace referencia a las alarmas * _WAKEUP, pero también ve la documentación de AlarmManager sobre eso para asegurarse de que comprende qué ofrecen las alarmas de activación frente a alarma de no activación.

Solo una nota. Puede obtener la llamada millis de tiempo de actividad:

 long uptimeMillis = SystemClock.elapsedRealtime(); 

Entonces, si desea disparar la alarma dentro de 30 segundos y desea usar el reloj de tiempo de actividad en lugar del reloj normal, puede hacer lo siguiente:

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

Siempre que desee 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.

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

 AlarmManager.ELAPSED_REALTIME_WAKEUP 

para configurar la alarma en un momento específico. la variable ‘intentName’ se usa en el filtro intencional 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 alarmIntens = new ArrayList(); 

//

  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 alarma es esto.

 public static void cancel(Context c) { AlarmManager am = (AlarmManager) c .getSystemService(Context.ALARM_SERVICE); // cancel all alarms for (Iterator 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(); } } 

Algunas notas importantes al elegir qué alarma usar : (para quienes ya leyeron los votos votados)

El valle de la muerte RTC_WAKEUP – cambio de hora:
Si el usuario ha cambiado el tiempo manualmente al pasado, la alarma no se activará y, en el futuro, la alarma se activará inmediatamente si RTC marca de tiempo RTC .
No use esta alarma para hacer ninguna verificación del lado del cliente / trabajos importantes porque tiene la posibilidad de fallar.

El significado de WAKEUP (Marshmallow y superior)
En general, no mucho. No se activará el dispositivo cuando esté idle o mientras alarmManager.setExactAndAllowWhileIdle alarmManager.setAndAllowWhileIdle , para ese alarmManager.setExactAndAllowWhileIdle o alarmManager.setAndAllowWhileIdle ( Doze & Idle )