Android AlarmManager - RTC_WAKEUP - ELAPSED_REALTIME_WAKEUP


87

Biri bana arasındaki farkı açıklayabilir AlarmManager.RTC_WAKEUPve AlarmManager.ELAPSED_REALTIME_WAKEUP? Belgeleri okudum ama yine de birini diğerinin üzerinde kullanmanın ne anlama geldiğini gerçekten anlamıyorum.

Örnek kod:

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

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

İki kod satırı ne kadar farklı çalışacak? Bu iki kod satırı birbirine göre ne zaman çalışacak?

Yardımın için minnettarım.

Yanıtlar:


141

AlarmManager.ELAPSED_REALTIME_WAKEUP type, başlatma zamanından itibaren alarmı tetiklemek için kullanılır:

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

cihaz başlatıldıktan 10 dakika sonra alarmın çalmasını sağlar .

Cihazın çalışma süresini ölçmek için cihaz açıldığında çalışmaya başlayan bir zamanlayıcı vardır ve bu, cihazın çalışma süresine göre alarmınızı tetikleyen tiptir.

Oysa AlarmManager.RTC_WAKEUPsaatin saatine göre alarmı tetikleyecektir. Örneğin, yaparsanız:

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

diğer yandan bu, alarmı bundan 30 saniye sonra tetikleyecektir .

AlarmManager.ELAPSED_REALTIME_WAKEUPtürü ile karşılaştırıldığında nadiren kullanılır AlarmManager.RTC_WAKEUP.


1
Bende böyle düşünmüştüm. Sadece biraz onaylamaya ihtiyacım vardı. Öyleyse şöyle bir şey yaptıysam: alarmManager.set (AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMills () + 30 * 1000, pendingIntent); tuhaf şeyler olabilir (ki düşündüğüm gibi çalışmadığını fark edene kadar da böyle olmuştu.
Camille Sévigny

2
Lütfen kodun System.currentTimeMillis()yerine geçmesi gerektiğini unutmayın System.currentTimeMills():)
HasanAboShally

17
"AlarmManager.ELAPSED_REALTIME_WAKEUP türü AlarmManager.RTC_WAKEUP ile karşılaştırıldığında nadiren kullanılır." Bu spekülasyon ve kötü bir tavsiye. Belgelere göre: developer.android.com/training/scheduling/alarms.html "Alarmınızın belirli bir aralıkta (örneğin, her yarım saatte bir) tetiklenmesi gerekiyorsa, geçen gerçek zamanlı türlerden birini kullanın. genel, bu daha iyi bir seçimdir. "
Jared Kells

1
@ mborsuk'un cevabı daha iyi ve şu cevabı düzeltiyor: için olduğu gibi geçen süre için RTC kullanmamalısınız thirtySecondsFromNow.
Micha F.

2
Oldukça iyi bir açıklama :)! Önemli bir yorum eklemek isterim: Android'deki resmi belgelerle ilgili olarak, "AlarmManager.ELAPSED_REALTIME_WAKEUP" kullanmak, bir sunucuya HTTP isteklerini ateşleyen bir uygulama söz konusu olduğunda ilginç bir şey olabilir ve herhangi bir şey oluşturmak istemezsiniz. web sunucunuza yükleyin. Saat 22: 30'da bir web sunucusunda bir GET gerçekleştiren binlerce Android cihazı düşünün: "AlarmManager.ELAPSED_REALTIME_WAKEUP", bu "binlerce" cihazın isteklerini tetiklemesini sağlayabilir, aynı zamanda, yükten kaçınarak :).
ivanleoncz

107

Şu anda kabul edilen ve yükseltilen cevaba rağmen, AlarmManager.ELAPSED_REALTIME * türleri ve SystemClock.elapsedRealtime () alarmlar ve zamanlama için her zaman RTC saatlerinden daha güvenilir olmuştur.

ELAPSED_REALTIME_WAKEUP'ı AlarmManager ile kullanmak, önyükleme zamanından itibaren monoton bir saate dayanır ve CPU güç tasarrufu modlarında olsa bile çalışmaya devam eder, bu nedenle genel amaçlı aralık zamanlaması için önerilen temeldir ". Yani,

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

PendingIntent ateşinizi 1 dakikada (60 * 1000 milisaniye) yapacak.

Oysa AlarmManager.RTC_WAKEUP, çağdan beri milisaniye cinsinden standart "duvar" süresi içindir. Yani,

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

alarmı bundan 60 saniye sonra da tetikleyebilir, ancak bu güvenilir değildir, çünkü SystemClock belgelerinde belirtildiği gibi :

Duvar saati kullanıcı veya telefon ağı tarafından ayarlanabilir (bkz. SetCurrentTimeMillis (uzun)), böylece zaman beklenmedik bir şekilde geriye veya ileriye atlayabilir. Bu saat, yalnızca bir takvim veya çalar saat uygulaması gibi gerçek dünya tarih ve saatleriyle yazışmalar önemli olduğunda kullanılmalıdır. Aralık veya geçen zaman ölçümleri farklı bir saat kullanmalıdır. System.currentTimeMillis () kullanıyorsanız, zamanın ne zaman değiştiğini öğrenmek için ACTION_TIME_TICK, ACTION_TIME_CHANGED ve ACTION_TIMEZONE_CHANGED Amaç yayınlarını dinlemeyi düşünün.

Ayrıca, soru yalnızca * _WAKEUP alarmlarına atıfta bulundu, ancak uyandırma ve uyanmama alarmlarının ne sağladığını anladığınızdan emin olmak için bununla ilgili AlarmManager belgelerine de bakın .


Cevabınız harika, ancak başvurumda, şu andan itibaren sadece 60 saniye değil, gerçek dünya tarih / saatlerine denk gelen alarmları ayarlamam gerekiyordu. Bu durumda, RTC_WAKEUP benim için en iyi çözüm.
Camille Sévigny

8
Sorun değil, ancak bu soruya daha doğru bir cevap ve şu anda kabul edilen cevaptaki şeyleri düzeltir.
mborsuk

Bu bilgi için +1, ancak bunun yerine elapsedRealtime()altında olduğuna dikkat edin . DÜZENLEME: ... Günlük oy sınırına ulaşıldı ...SystemClockSystem
Jorge Fuentes González

Bu, oradaki konudaki en iyi cevaplardan biridir. 50 metre yüksekliğindeki samanlıkta bir iğne arıyordum (aka "kodumdaki bir böcek!") Ve cevabınız beni doğrudan iğneye götürdü!
AlxDroidDev

17

Sadece bir not. Çalışma zamanı milis çağrısını alabilirsiniz:

long uptimeMillis =  SystemClock.elapsedRealtime();

Bu nedenle, alarmı bundan 30 saniye sonra çalıştırmak istiyorsanız ve normal saat yerine çalışma saatini kullanmak istiyorsanız, şunları yapabilirsiniz:

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

Belirli bir tarih / saat yerine geçen bir zamanı kontrol etmek istediğinizde, çalışma süresini kullanmak en iyisidir. Bunun nedeni, cihazda kullanıcı tarafından ayarlanan mevcut zamanın, kullanıcı ayarları kullanarak değiştirmesi durumunda değişebilir.


3
"Geçen süreyi her kontrol etmek istediğinizde" bunu kullanmak için +1. Kesinlikle mantıklı.
sulai

Yine sadece vurgulamak için: Anladığım kadarıyla, cihaz kapanma gibi bir şey olmadıkça, bundan 30 saniye sonra kesinlikle ateşlenecek. Somut olarak, RTC_WAKEUP kullanmanın sorunu, teoride, bundan 15 saniye sonra, Ekim ayının sonuna yakın bir Cumartesi günü 01:00 gibi bir şeye dönüşmesi ve sistem saatinin 1 saat geriye gitmesi (ABD'de ve çoğu En azından Avrupa), bu durumda alarm, ayarlandıktan 1 saat 30 saniye sonrasına kadar gerçekten tetiklenmez.
Yannick

2

Bu sorunu kendi projemde bu şekilde programladım. aşağıdaki kodda kullanıyorum

AlarmManager.ELAPSED_REALTIME_WAKEUP

belirli bir saatte alarm kurmak için. 'intentName' değişkeni, bu alarmı almak için intentFilter'da kullanılır. çünkü bu türden birçok alarmı çalıştırıyorum. tüm alarmları iptal ettiğimde. iptal yöntemini kullanıyorum. altta verilmiştir.

// alarmları tutmak ve gerektiğinde iptal etmek için

     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 işlevi nerede budur:

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

alarm iptal işlevi budur.

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

1

Hangi alarmın kullanılacağını seçerken bazı önemli notlar : (oyları zaten okuyanlar için)

RTC_WAKEUP Ölüm vadisi - saat değişikliği:
kullanıcı Kapanmayan alarma geçmiş elle değişiklik zamanı vardır ve gelecekte alarmı geçmiş eğer o hemen çıkmak neden olacaksa RTCdamgası.
Yapmayın başarısız şansına sahip olduğundan herhangi bir istemci tarafı doğrulama / önemli işler yapmak için bu alarmı kullanırız.

WAKEUP Anlamı (yukarıda Hatmi ve)
Genel olarak - çok değil. Bunun için veya ( Doze & Idle ) idleiçerisindeyken veya içindeyken cihazı uyandırmayacakdozealarmManager.setExactAndAllowWhileIdlealarmManager.setAndAllowWhileIdle

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.