AlarmManager — είναι μια υπηρεσία συστήματος Android που επιτρέπει στις εφαρμογές να εκτελούν εργασίες σε καθορισμένο χρόνο, ακόμα κι αν η εφαρμογή δεν εκτελείται ή η συσκευή βρίσκεται σε κατάσταση αναστολής λειτουργίας. Σε αντίθεση με το JobScheduler ή το WorkManager, το AlarmManager εγγυάται την ακρίβεια ενεργοποίησης, καθιστώντας το απαραίτητο για ξυπνητήρια, υπενθυμίσεις ημερολογίου και εργασίες κρίσιμες ως προς τον χρόνο εκτέλεσης. Σύμφωνα με το Android Developers, 2026, από το Android 4.4 το setRepeating συμπεριφέρεται ως ανακριβής επανάληψη, και για ακριβή ξυπνητήρια απαιτείται setExact ή setAlarmClock.
Κύρια σημεία
AlarmManager — είναι μια υπηρεσία συστήματος Android που παρέχει API για προγραμματισμό εργασιών με ακριβή ή κατά προσέγγιση χρόνο εκτέλεσης. Υπάρχει από την πρώτη έκδοση του Android και παραμένει ο μόνος αξιόπιστος τρόπος εκτέλεσης κώδικα σε μια συγκεκριμένη στιγμή, ανεξάρτητα από την κατάσταση της εφαρμογής και της συσκευής.
Η αρχή λειτουργίας είναι απλή: η εφαρμογή στέλνει στο σύστημα ένα PendingIntent με καθορισμό του χρόνου ενεργοποίησης. Όταν φτάσει η επιθυμητή στιγμή, το σύστημα στέλνει ένα Intent στον εγγεγραμμένο BroadcastReceiver ή εκκινεί ένα Service. Ακόμα κι αν η συσκευή ήταν σε κατάσταση αναστολής, ένα WakeLock επιτρέπει στον επεξεργαστή να αφυπνιστεί και να επεξεργαστεί το συμβάν.
Κύριος τομέας εφαρμογής του AlarmManager — εργασίες που απαιτούν ακριβή χρόνο: ξυπνητήρια, υπενθυμίσεις ημερολογίου, εκκίνηση μακροχρόνιων λειτουργιών σε συγκεκριμένη ώρα. Για εργασίες όπου η ακρίβεια δεν είναι κρίσιμη (συγχρονισμός μία φορά την ημέρα), η Google συνιστά WorkManager ή JobScheduler, καθώς είναι πιο ενεργειακά αποδοτικά.
AlarmManager λαμβάνει από την εφαρμογή ένα PendingIntent και τον χρόνο ενεργοποίησης. Το σύστημα αποθηκεύει αυτό το αίτημα στον εσωτερικό του προγραμματιστή και αφυπνίζει τον επεξεργαστή την καθορισμένη ώρα για να παραδώσει το Intent. Ο προγραμματιστής πρέπει να εγγράψει εκ των προτέρων έναν BroadcastReceiver που θα επεξεργαστεί αυτό το Intent.
AlarmManager υποστηρίζει 4 τύπους ξυπνητηριών: ELAPSED_REALTIME (χρόνος από την εκκίνηση, δεν αφυπνίζει), RTC (πραγματικός χρόνος, δεν αφυπνίζει), ELAPSED_REALTIME_WAKEUP (χρόνος από την εκκίνηση, αφυπνίζει τη συσκευή) και RTC_WAKEUP (πραγματικός χρόνος, αφυπνίζει). Οι εκδόσεις WAKEUP είναι απαραίτητες αν η εργασία πρέπει να εκτελεστεί ακόμα κι όταν η συσκευή κοιμάται.
| Τύπος | Χρόνος | Αφυπνίζει | Παράδειγμα |
|---|---|---|---|
| ELAPSED_REALTIME | από εκκίνηση | όχι | χρονοδιακόπτης λειτουργίας |
| RTC | Unix timestamp | όχι | καταγραφή |
| ELAPSED_REALTIME_WAKEUP | από εκκίνηση | ναι | περιοδική εργασία |
| RTC_WAKEUP | Unix timestamp | ναι | ξυπνητήρι |
Από το Android 12 (API 31), για χρήση ακριβών ξυπνητηριών (setExact) απαιτείται η άδεια SCHEDULE_EXACT_ALARM. Ο χρήστης μπορεί να την ανακαλέσει μέσω των ρυθμίσεων. Για εφαρμογές που χρειάζονται ακριβές ξυπνητήρι με εμφάνιση (π.χ. ρολόι), χρησιμοποιείται το USE_EXACT_ALARM, το οποίο χορηγείται κατά την εγκατάσταση.
AlarmManager παρέχει τρεις κύριες μεθόδους για προγραμματισμό εργασιών. Η επιλογή μεθόδου καθορίζει την ακρίβεια ενεργοποίησης και την επίδραση στην κατανάλωση ενέργειας της συσκευής.
set — η βασική μέθοδος για εφάπαξ ανακριβή ενεργοποίηση. Το σύστημα μπορεί να μετατοπίσει τον χρόνο έως και λίγα λεπτά για ομαδοποίηση με άλλα συμβάντα. Κατάλληλο για εργασίες όπου η ακρίβεια δεν είναι κρίσιμη: υπενθύμιση για είσοδο στην εφαρμογή.
setRepeating — η μέθοδος για περιοδικές επαναλήψεις. Από το Android 4.4 (API 19) το setRepeating έγινε ανακριβές — τα διαστήματα μπορεί να ποικίλλουν. Το σύστημα δεν εγγυάται πλέον σταθερή περίοδο. Αντί για setRepeating, συνιστάται η χρήση setExact με μη αυτόματο επαναπρογραμματισμό ή WorkManager με PeriodicWorkRequest.
setExact — η μέθοδος για ακριβή εφάπαξ ενεργοποίηση. Το σύστημα αφυπνίζει τη συσκευή όσο το δυνατόν πλησιέστερα στον καθορισμένο χρόνο. setAlarmClock — μια ειδική περίπτωση του setExact, που επιπλέον εμφανίζει ένα εικονίδιο ξυπνητηριού στη γραμμή κατάστασης και έχει την υψηλότερη προτεραιότητα μεταξύ όλων των τύπων ξυπνητηριών.
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
// Ακριβές εφάπαξ ξυπνητήρι
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
this, 0, intent,
PendingIntent.FLAG_IMMUTABLE
)
alarmManager.setAlarmClock(
AlarmManager.AlarmClockInfo(
targetTime, pendingIntent
),
pendingIntent
)
Τυπικό σενάριο — δημιουργία καθημερινής υπενθύμισης σε συγκεκριμένη ώρα. Για αυτό χρησιμοποιείται RTC_WAKEUP με setExact. Κατά την ενεργοποίηση, ο BroadcastReceiver εκκινεί μια ειδοποίηση ή ένα Service. Μετά την επεξεργασία, η εργασία πρέπει να επαναπρογραμματιστεί για την επόμενη ημέρα.
class ReminderReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE)
as NotificationManager
val notification = NotificationCompat.Builder(
context, "reminder_channel"
)
.setContentTitle("Υπενθύμιση")
.setContentText("Ήρθε η ώρα να εκτελέσετε την εργασία")
.setSmallIcon(R.drawable.ic_reminder)
.build()
notificationManager.notify(1001, notification)
}
}
Για καθημερινή επανάληψη χρησιμοποιείται setExact με υπολογισμό της επόμενης ενεργοποίησης. Στο Intent μπορούν να σταλούν σημαίες για αναγνώριση διαφορετικών τύπων υπενθυμίσεων. Βεβαιωθείτε ότι ο BroadcastReceiver είναι εγγεγραμμένος στο AndroidManifest.xml με επεξεργασία της ενέργειας WAKEUP.
fun scheduleDailyReminder(context: Context, hour: Int, minute: Int) {
val calendar = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, hour)
set(Calendar.MINUTE, minute)
set(Calendar.SECOND, 0)
if (before(Calendar.getInstance())) {
add(Calendar.DAY_OF_MONTH, 1)
}
}
val alarmManager =
context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
pendingIntent
)
}
AlarmManager — ένα ισχυρό αλλά ενεργοβόρο εργαλείο. Κάθε ξυπνητήρι WAKEUP βγάζει τη συσκευή από την κατάσταση αναστολής, γεγονός που καταναλώνει μπαταρία. Η Google συνιστά την ελαχιστοποίηση της χρήσης ακριβών ξυπνητηριών και την προτίμηση του setExactAndAllowWhileIdle σε Android 6+ για μείωση της επίδρασης στο Doze Mode. Για περιοδικές εργασίες χωρίς απαίτηση ακρίβειας, χρησιμοποιήστε WorkManager με PeriodicWorkRequest, το οποίο δεν απαιτεί αφύπνιση της συσκευής και δεν καταναλώνει μπαταρία σε κάθε εκτέλεση.
Για δοκιμή του AlarmManager χρησιμοποιήστε το TestAlarmManager από το Android Test Framework. Επιτρέπει την προσομοίωση ενεργοποίησης ξυπνητηριού χωρίς αναμονή για πραγματικό χρόνο. Στο Robolectric είναι διαθέσιμο το ShadowAlarmManager, το οποίο παρεμποδίζει κλήσεις set, setExact και setRepeating, παρέχοντας μεθόδους για εξαναγκασμένη ενεργοποίηση και έλεγχο του αριθμού των προγραμματισμένων εργασιών. Για μοναδιαίες δοκιμές του BroadcastReceiver χρησιμοποιήστε το Robolectric.getForegroundScheduler(). Επίσης διατίθεται δοκιμή Espresso με IdlingResource που αναμένει την ενεργοποίηση του ξυπνητηριού σε δοκιμές ολοκλήρωσης.
Αν η εφαρμογή χρησιμοποιεί AlarmManager για περιοδικές εργασίες που δεν απαιτούν ακριβή χρόνο, εξετάστε τη μετάβαση σε WorkManager. Το PeriodicWorkRequest με ελάχιστο διάστημα 15 λεπτών αντικαθιστά το setRepeating, ενώ το WorkManager εγγυάται εκτέλεση μετά από επανεκκίνηση, διαχειρίζεται το Doze Mode και δεν απαιτεί άδεια SCHEDULE_EXACT_ALARM. Για χρονικά κρίσιμες εργασίες (ξυπνητήρι στις 7 το πρωί), το AlarmManager παραμένει η μόνη σωστή επιλογή. Η βέλτιστη στρατηγική — χρησιμοποιήστε AlarmManager μόνο για ξυπνητήρια με setAlarmClock και μεταφέρετε όλες τις άλλες εργασίες παρασκηνίου στο WorkManager.
Για περιοδικές εργασίες χωρίς απαίτηση ακρίβειας χρησιμοποιήστε WorkManager με PeriodicWorkRequest. Για εργασίες με ακριβή χρόνο αλλά μη κρίσιμες για ενεργοποίηση σε κατάσταση αναστολής — setExact χωρίς WAKEUP. Και μόνο για ξυπνητήρια με υποχρεωτική αφύπνιση — setAlarmClock ή RTC_WAKEUP.
Επίσης είναι σημαντικό να ελέγχετε την ύπαρξη της άδειας SCHEDULE_EXACT_ALARM σε Android 12+. Εάν η άδεια δεν έχει χορηγηθεί, το setExact θα λειτουργεί ως κανονικό set (ανακριβώς). Χρησιμοποιήστε το AlarmManager.canScheduleExactAlarms() για έλεγχο. Ελλείψει άδειας, μπορείτε να προτείνετε στον χρήστη να μεταβεί στις ρυθμίσεις μέσω Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM).
Ένα κρίσιμο χαρακτηριστικό του AlarmManager — όλα τα προγραμματισμένα ξυπνητήρια επαναφέρονται μετά από επανεκκίνηση της συσκευής. Για την επαναφορά τους, πρέπει να δηλώσετε έναν BroadcastReceiver που επεξεργάζεται το Intent.ACTION_BOOT_COMPLETED και να επαναπρογραμματίσετε όλα τα ενεργά ξυπνητήρια στη μέθοδο onReceive. Χωρίς αυτό, ο χρήστης θα χάσει όλες τις υπενθυμίσεις μετά την απενεργοποίηση και ενεργοποίηση του τηλεφώνου.
class BootReceiver : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent
) {
if (intent.action ==
Intent.ACTION_BOOT_COMPLETED
) {
val prefs =
context.getSharedPreferences("alarms", 0)
val savedTime =
prefs.getLong("next_alarm", 0L)
if (savedTime > System.currentTimeMillis()) {
scheduleReminder(context, savedTime)
}
}
}
}
Στην πράξη, το AlarmManager παραμένει η καλύτερη λύση για εφαρμογές ξυπνητηριού, ημερολογίου, υπενθυμίσεων λήψης φαρμάκων και οποιεσδήποτε εργασίες όπου ο χρόνος ενεργοποίησης είναι κρίσιμος για τον χρήστη. Για όλα τα άλλα σενάρια εργασίας παρασκηνίου, προτιμώνται το WorkManager ή το JobScheduler.
Κατά την επιλογή μεταξύ AlarmManager και WorkManager, ακολουθήστε τον κανόνα: αν ο χρήστης ζήτησε ρητά υπενθύμιση στις 14:30 — χρησιμοποιήστε AlarmManager με setAlarmClock. Αν η εργασία πρέπει να εκτελείται «περίπου μία φορά την ώρα» — το WorkManager με PeriodicWorkRequest θα είναι πιο ενεργειακά αποδοτικό και αξιόπιστο.
Συχνές ερωτήσεις
Και οι δύο μέθοδοι εγγυώνται ακριβή ενεργοποίηση, αλλά το setAlarmClock επιπλέον εμφανίζει ένα εικονίδιο ξυπνητηριού στη γραμμή κατάστασης και ενημερώνει το σύστημα ότι αυτό είναι ξυπνητήρι για τον χρήστη. Σε Android 6+ το setAlarmClock έχει ανοσία στο Doze Mode, ενώ το setExact μπορεί να καθυστερήσει.
Μετά από επανεκκίνηση, όλα τα προγραμματισμένα ξυπνητήρια επαναφέρονται. Για επαναφορά, πρέπει να εγγράψετε έναν BroadcastReceiver για την ενέργεια BOOT_COMPLETED και να επαναπρογραμματίσετε όλες τις εργασίες στο onReceive. Χωρίς αυτό, κανένα ξυπνητήρι δεν θα λειτουργήσει μετά την ενεργοποίηση της συσκευής.
Από το API 19, το setRepeating έγινε ανακριβές — το σύστημα μπορεί να μετατοπίζει τα διαστήματα για εξοικονόμηση ενέργειας. Αντί αυτού, χρησιμοποιήστε setExact με μη αυτόματο επαναπρογραμματισμό ή WorkManager με PeriodicWorkRequest, το οποίο παρέχει πιο προβλέψιμη συμπεριφορά.
Για setExact απαιτείται η άδεια SCHEDULE_EXACT_ALARM, την οποία ο χρήστης μπορεί να χορηγήσει ή να ανακαλέσει στις ρυθμίσεις. Για setAlarmClock με εμφάνιση στη διεπαφή ρολογιού, χρησιμοποιείται το USE_EXACT_ALARM, το οποίο χορηγείται αυτόματα κατά την εγκατάσταση από το κατάστημα.
Όχι, το AlarmManager λειτουργεί πάντα μέσω PendingIntent. Μπορεί να είναι PendingIntent.getBroadcast για BroadcastReceiver, PendingIntent.getService για Service ή PendingIntent.getActivity για Activity. Χωρίς PendingIntent, το σύστημα δεν θα μπορέσει να παραδώσει το συμβάν στην εφαρμογή.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης