Android AlarmManager - RTC_WAKEUP เทียบกับ ELAPSED_REALTIME_WAKEUP


87

ใครสามารถอธิบายความแตกต่างระหว่างAlarmManager.RTC_WAKEUPและAlarmManager.ELAPSED_REALTIME_WAKEUP? ฉันได้อ่านเอกสารแล้ว แต่ก็ยังไม่เข้าใจความหมายของการใช้เอกสารอื่น ๆ

รหัสตัวอย่าง:

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

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

โค้ดสองบรรทัดจะแตกต่างกันอย่างไร โค้ดสองบรรทัดนั้นจะทำงานสัมพันธ์กันเมื่อใด

ฉันขอขอบคุณสำหรับความช่วยเหลือของคุณ

คำตอบ:


141

AlarmManager.ELAPSED_REALTIME_WAKEUP type ใช้เพื่อกระตุ้นการเตือนตั้งแต่เวลาบูต:

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

จริงจะทำให้ไปปลุกปิด10 นาทีหลังจากที่รองเท้าอุปกรณ์

มีตัวจับเวลาที่เริ่มทำงานเมื่ออุปกรณ์บูทขึ้นเพื่อวัดเวลาพร้อมใช้งานของอุปกรณ์และเป็นประเภทที่เรียกใช้การปลุกของคุณตามเวลาพร้อมใช้งานของอุปกรณ์

ในขณะที่AlarmManager.RTC_WAKEUPจะเรียกปลุกตามเวลาของนาฬิกา ตัวอย่างเช่นหากคุณทำ:

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

นี้บนมืออื่น ๆ ที่จะเรียกปลุก30 วินาทีจากนี้

AlarmManager.ELAPSED_REALTIME_WAKEUPAlarmManager.RTC_WAKEUPประเภทไม่ค่อยจะใช้เมื่อเทียบกับ


1
นั่นคือสิ่งที่ฉันคิดว่า. ฉันแค่ต้องการการยืนยัน ดังนั้นถ้าฉันทำสิ่งนี้: alarmManager.set (AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMills () + 30 * 1000, pendingIntent); สิ่งแปลก ๆ อาจเกิดขึ้น (ซึ่งเป็นสิ่งที่ฉันมีจนกระทั่งฉันสังเกตว่ามันไม่ได้ผลอย่างที่คิด
Camille Sévigny

2
โปรดทราบว่าควรใช้รหัสSystem.currentTimeMillis()แทนSystem.currentTimeMills():)
HasanAboShally

17
"AlarmManager.ELAPSED_REALTIME_WAKEUP แทบไม่ได้ใช้เมื่อเทียบกับ AlarmManager.RTC_WAKEUP" นี่คือการคาดเดาและคำแนะนำที่ไม่ดี ตามเอกสารประกอบ: developer.android.com/training/scheduling/alarms.html "หากคุณต้องการให้สัญญาณเตือนดังขึ้นในช่วงเวลาใดช่วงหนึ่ง (เช่นทุกๆครึ่งชั่วโมง) ให้ใช้ประเภทเรียลไทม์ที่ผ่านไปประเภทใดเวลาหนึ่งใน โดยทั่วไปนี่เป็นทางเลือกที่ดีกว่า "
Jared Kells

1
คำตอบ @ mborsuk จะทำได้ดีกว่าและแก้ไขคำตอบนี้: คุณไม่ควรใช้ RTC thirtySecondsFromNowสำหรับเวลาที่ผ่านไปเช่นสำหรับ
Micha F.

2
คำอธิบายค่อนข้างดี :)! ฉันต้องการเพิ่มความคิดเห็นที่สำคัญ: เกี่ยวกับเอกสารอย่างเป็นทางการจาก Android การใช้ "AlarmManager.ELAPSED_REALTIME_WAKEUP" อาจเป็นสิ่งที่น่าสนใจเมื่อพูดถึงแอปพลิเคชันที่ส่งคำขอ HTTP ไปยังเซิร์ฟเวอร์และคุณไม่ต้องการสร้าง โหลดบนเว็บเซิร์ฟเวอร์ของคุณ ลองนึกถึงอุปกรณ์ Android หลายพันเครื่องที่ใช้ GET บนเว็บเซิร์ฟเวอร์เวลา 22.30 น.: เนื่องจากอุปกรณ์ทำงานตลอดเวลาบูตเครื่อง "AlarmManager.ELAPSED_REALTIME_WAKEUP" อาจทำให้อุปกรณ์ "หลายพันรายการ" ส่งคำขอได้ ในเวลาเดียวกันหลีกเลี่ยงการโหลด :)
ivanleoncz

107

แม้จะมีคำตอบที่ได้รับการยอมรับและได้รับการโหวตแล้ว แต่ประเภท AlarmManager.ELAPSED_REALTIME * พร้อมกับ SystemClock.elapsedRealtime () มีความน่าเชื่อถือมากกว่านาฬิกา RTC สำหรับการเตือนภัยและเวลาเสมอ

การใช้ ELAPSED_REALTIME_WAKEUP กับ AlarmManager จะใช้นาฬิกาโมโนโทนิกเริ่มตั้งแต่เวลาบูต " และยังคงทำเครื่องหมายแม้ CPU จะอยู่ในโหมดประหยัดพลังงานดังนั้นจึงเป็นพื้นฐานที่แนะนำสำหรับการกำหนดช่วงเวลาสำหรับวัตถุประสงค์ทั่วไป " ดังนั้น,

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

จะทำให้ PendingIntent ของคุณเริ่มทำงานใน 1 นาที (60 * 1,000 มิลลิวินาที)

ในขณะที่ AlarmManager.RTC_WAKEUP เป็นเวลามาตรฐาน "wall" ในหน่วยมิลลิวินาทีนับตั้งแต่ยุค ดังนั้น,

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

นอกจากนี้ยังอาจกระตุ้นการเตือน 60 วินาทีนับจากนี้ แต่ไม่น่าเชื่อถือเนื่องจากตามที่ระบุไว้ในเอกสาร SystemClock :

ผู้ใช้หรือเครือข่ายโทรศัพท์สามารถตั้งค่านาฬิกาแขวนได้ (ดู setCurrentTimeMillis (แบบยาว)) ดังนั้นเวลาอาจกระโดดถอยหลังหรือไปข้างหน้าโดยไม่สามารถคาดเดาได้ ควรใช้นาฬิกานี้เมื่อการติดต่อกับวันที่และเวลาในโลกแห่งความเป็นจริงมีความสำคัญเช่นในแอปพลิเคชันปฏิทินหรือนาฬิกาปลุก การวัดช่วงเวลาหรือเวลาที่ผ่านไปควรใช้นาฬิกาที่แตกต่างกัน หากคุณกำลังใช้ System.currentTimeMillis () ให้ลองฟังการถ่ายทอด ACTION_TIME_TICK, ACTION_TIME_CHANGED และ ACTION_TIMEZONE_CHANGED Intent เพื่อดูว่าเวลาเปลี่ยนไปเมื่อใด

นอกจากนี้คำถามยังอ้างอิงเฉพาะการเตือนภัย * _WAKEUP เท่านั้น แต่โปรดดูเอกสารAlarmManagerด้วยเพื่อให้แน่ใจว่าคุณเข้าใจว่าการปลุกและการปลุกแบบไม่ปลุกมีให้อย่างไร


คำตอบของคุณดีมาก แต่ในแอปพลิเคชันของฉันฉันต้องตั้งนาฬิกาปลุกที่ใกล้เคียงกับวันที่ / เวลาในโลกแห่งความเป็นจริงไม่ใช่แค่ 60 วินาทีนับจากนี้ ในกรณีนี้ RTC_WAKEUP เป็นทางออกที่ดีที่สุดสำหรับฉัน
Camille Sévigny

8
ไม่เป็นไร แต่นี่เป็นคำตอบที่ถูกต้องกว่าสำหรับคำถามและแก้ไขสิ่งต่างๆในคำตอบที่ยอมรับในปัจจุบัน
mborsuk

+1 สำหรับข้อมูลนี้ แต่ทราบว่าelapsedRealtime()อยู่ภายใต้การแทนSystemClock Systemแก้ไข: ... ถึงขีด จำกัด การโหวตรายวันแล้ว ...
Jorge Fuentes González

นี่เป็นหนึ่งในคำตอบที่ดีที่สุดในประเด็นนี้ ฉันกำลังค้นหาเข็มในกองหญ้าสูง 50 เมตร (หรือที่เรียกว่า "แมลงในรหัสของฉัน!") และคำตอบของคุณทำให้ฉันตรงไปที่เข็ม!
AlxDroidDev

17

เพียงแค่ทราบ คุณสามารถรับการโทรมิลลิวินาทีเวลาทำงานได้:

long uptimeMillis =  SystemClock.elapsedRealtime();

ดังนั้นหากคุณต้องการเริ่มการปลุก 30 วินาทีนับจากนี้และคุณต้องการใช้นาฬิกาออนไลน์แทนนาฬิกาปกติคุณสามารถทำได้ดังนี้

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

เมื่อใดก็ตามที่คุณต้องการตรวจสอบเวลาที่ผ่านไปแทนที่จะเป็นวัน / เวลาที่เฉพาะเจาะจงควรใช้ช่วงเวลาที่พร้อมใช้งาน นั่นเป็นเพราะเวลาปัจจุบันที่กำหนดโดยผู้ใช้ในอุปกรณ์สามารถเปลี่ยนแปลงได้หากผู้ใช้เปลี่ยนโดยใช้การตั้งค่า


3
+1 เพื่อชี้ให้ใช้ "เมื่อใดก็ตามที่คุณต้องการตรวจสอบเวลาที่ผ่านไป" เหมาะสมอย่างยิ่ง
sulai

อีกครั้งที่ต้องเครียด: ความเข้าใจของฉันคือสิ่งนี้จะเริ่มขึ้นอย่างแน่นอนใน 30 วินาทีนับจากนี้เว้นแต่จะมีอะไรเกิดขึ้นเช่นอุปกรณ์ปิดตัวลง ฉันคิดว่าปัญหาในการใช้ RTC_WAKEUP ตามทฤษฎีแล้ว 15 วินาทีจากนี้เป็นไปได้ว่ามันจะกลายเป็นเวลา 1:00 น. ในวันเสาร์ใกล้สิ้นเดือนตุลาคมและนาฬิการะบบจะย้อนกลับ 1 ชั่วโมง (ในสหรัฐอเมริกาและส่วนใหญ่ ยุโรปเป็นอย่างน้อย) ดังนั้นสัญญาณเตือนจะไม่เริ่มจริงจนกว่าจะตั้งเวลา 1 ชั่วโมง 30 วินาที
Yannick

2

ฉันตั้งโปรแกรมปัญหานี้ในโครงการของตัวเองด้วยวิธีนี้ ในโค้ดด้านล่างที่ฉันใช้

AlarmManager.ELAPSED_REALTIME_WAKEUP

เพื่อตั้งปลุกในเวลาที่กำหนด ตัวแปร 'ชื่อเจตนา' ถูกใช้ในตัวกรองความตั้งใจเพื่อรับสัญญาณเตือนนี้ เพราะฉันส่งสัญญาณเตือนประเภทนี้หลายครั้ง เมื่อฉันยกเลิกการปลุกทั้งหมด ฉันใช้วิธียกเลิก ให้ที่ด้านล่าง

// เพื่อพักการเตือนและยกเลิกเมื่อจำเป็น

     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 คือ:

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

ฟังก์ชั่นยกเลิกการเตือนคือนี่

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

หมายเหตุสำคัญบางประการในการเลือกนาฬิกาปลุกที่จะใช้ : (สำหรับผู้ที่อ่านโหวตที่โหวตแล้ว)

RTC_WAKEUP หุบเขาตาย - เปลี่ยนเวลา:
หากผู้ใช้มีเวลาเปลี่ยนแปลงตนเองเพื่อการเตือนภัยที่ผ่านมาจะไม่ออกไปและในอนาคตจะทำให้เกิดการเตือนภัยที่จะไปปิดทันทีถ้ามันผ่านRTCการประทับเวลา
อย่าใช้การเตือนนี้เพื่อทำการตรวจสอบฝั่งไคลเอ็นต์ / งานที่สำคัญเนื่องจากมีโอกาสที่จะล้มเหลว

WAKEUP ความหมาย (Marshmallow ขึ้นไป)
โดยทั่วไป - ไม่มาก จะไม่ปลุกอุปกรณ์เมื่อidleอยู่ในขณะdozeนั้นalarmManager.setExactAndAllowWhileIdleหรือalarmManager.setAndAllowWhileIdle( Doze & Idle )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.