web-dev-qa-db-fra.com

Android AlarmManager - RTC_WAKEUP vs ELAPSED_REALTIME_WAKEUP

Est-ce que quelqu'un peut m'expliquer la différence entre AlarmManager.RTC_WAKEUP et AlarmManager.ELAPSED_REALTIME_WAKEUP? J'ai lu la documentation, mais je ne comprends toujours pas vraiment l'implication d'utiliser l'un sur l'autre.

Exemple de code:

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

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

Quelle différence y aura-t-il entre les deux lignes de code? Quand ces deux lignes de code s'exécuteront-elles l'une par rapport à l'autre?

J'apprécie ton aide.

82

AlarmManager.ELAPSED_REALTIME_WAKEUP type est utilisé pour déclencher l'alarme depuis le démarrage:

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

fait réellement sonner l'alarme 10 min après le démarrage de l'appareil

Il y a une minuterie qui démarre lorsque le périphérique démarre pour mesurer son temps de disponibilité. Il s'agit du type qui déclenche votre alarme en fonction du temps de disponibilité du périphérique.

Alors que AlarmManager.RTC_WAKEUP déclenchera l’alarme en fonction de l’heure de l’horloge. Par exemple si vous le faites:

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

cela, par contre, déclenchera l'alarme dans 30 secondes

Le type AlarmManager.ELAPSED_REALTIME_WAKEUP est rarement utilisé comparé à AlarmManager.RTC_WAKEUP

128
Rejinderi

Malgré la réponse actuellement acceptée et améliorée, les types AlarmManager.ELAPSED_REALTIME *, ainsi que SystemClock.elapsedRealtime () ont toujours été plus fiables que les horloges RTC pour les alarmes et la synchronisation.

L'utilisation de ELAPSED_REALTIME_WAKEUP avec AlarmManager repose sur une horloge monotone à partir de l'heure de démarrage "et continue de cocher même lorsque la CPU est en mode d'économie d'énergie. Il en va de la base recommandée pour la synchronisation d'intervalle". Alors,

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

fera votre feu en attente en 1 min (60 * 1000 millisecondes).

Tandis que AlarmManager.RTC_WAKEUP correspond au temps "mural" standard en millisecondes depuis l'époque. Alors,

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

peut également déclencher l’alarme dans 60 secondes, mais pas de manière fiable, car comme indiqué dans la documentation SystemClock :

L'horloge murale peut être réglée par l'utilisateur ou par le réseau téléphonique (voir SetCurrentTimeMillis (long)), afin que le temps puisse reculer ou expédie de manière imprévisible. Cette horloge ne doit être utilisée que lorsque la correspondance avec les dates et heures du monde réel est importante, telle que dans une application de calendrier ou de réveil. Intervalle ou temps écoulé les mesures doivent utiliser une horloge différente. Si vous utilisez System.currentTimeMillis (), envisagez d'écouter le fichier ACTION_TIME_TICK, ACTION_TIME_CHANGED et ACTION_TIMEZONE_CHANGED Intention diffuse pour savoir quand l’heure change.

En outre, la question ne faisait référence qu'aux alarmes * _WAKEUP, mais reportez-vous également à la documentation AlarmManager pour vous assurer que vous comprenez bien ce que fournissent les alarmes réveil ou non. 

103
mborsuk

Juste une note. Vous pouvez obtenir l'appel millis de disponibilité appelant:

long uptimeMillis =  SystemClock.elapsedRealtime();

Donc, si vous voulez déclencher l'alarme dans 30 secondes et que vous voulez utiliser l'horloge de disponibilité au lieu de l'horloge normale, vous pouvez faire:

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

Lorsque vous souhaitez vérifier le temps écoulé au lieu d'une date/heure spécifique, il est préférable d'utiliser le temps de disponibilité. En effet, l'heure actuelle définie par l'utilisateur sur l'appareil peut être modifiée si l'utilisateur le modifie à l'aide des paramètres.

16
Ena

J'ai programmé ce problème dans mon propre projet de cette façon. dans le code ci-dessous j'utilise

AlarmManager.ELAPSED_REALTIME_WAKEUP

pour régler l’alarme à un moment précis . la variable 'intentName' est utilisée dans intentFilter pour recevoir cette alarme. parce que je déclenche de nombreuses alarmes de ce type. quand j'annule toutes les alarmes. J'utilise la méthode cancel. donné en bas.

// pour maintenir les alarmes et annuler si nécessaire

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

où la fonction span est la suivante:

 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 fonction d'annulation d'alarme est la suivante.

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

Quelques notes importantes lorsque choisir quelle alarme utiliser :( pour qui a déjà lu les votes positifs)

LeRTC_WAKEUPvallée de la mort - changement d'heure: 
Si l'utilisateur a modifié manuellement l'heure, l'alarme ne se déclenche pas et, à l'avenir, l'alarme s'éteindra immédiatement si elle dépasse l'horodatage RTC.
Ne pas utilisez cette alarme pour effectuer des tâches de vérification/importantes côté client car elles risquent d'échouer. 

_ {LeWAKEUPsignification (guimauve et ci-dessus)} _
En général - pas grand chose. Ne réveillera pas le périphérique lorsque idle ou en étant dans doze, pour ce alarmManager.setExactAndAllowWhileIdle ou alarmManager.setAndAllowWhileIdle ( Assoupi et inactif )

0
Andro Secy