AlarmManager: Các khái niệm chính và làm việc với báo thức

Tác giả: IT Sectr Đã đăng: 2026-03-28 Thời gian đọc: 8 phút

AlarmManager là một dịch vụ hệ thống Android cho phép ứng dụng thực thi tác vụ vào thời gian đã chỉ định, ngay cả khi ứng dụng không chạy hoặc thiết bị ở chế độ ngủ. Không giống như JobScheduler hay WorkManager, AlarmManager đảm bảo độ chính xác khi kích hoạt, khiến nó không thể thiếu cho báo thức, lời nhắc lịch và các tác vụ quan trọng về thời gian thực thi. Theo Android Developers, 2026, từ Android 4.4, setRepeating hoạt động như một lần lặp không chính xác và báo thức chính xác yêu cầu setExact hoặc setAlarmClock.

Những điểm chính

  • AlarmManager là dịch vụ hệ thống Android để thực thi tác vụ vào thời gian chính xác, hoạt động ngay cả ở chế độ ngủ.
  • Các loại báo thức bao gồm ELAPSED_REALTIME, RTC, ELAPSED_REALTIME_WAKEUP và RTC_WAKEUP — có và không đánh thức.
  • setExact đảm bảo kích hoạt chính xác trên Android 4.4+, nhưng tiêu thụ nhiều pin hơn.
  • setAlarmClock là phương thức duy nhất mà hệ thống đảm bảo thực thi đúng giờ trên Android 6+.
  • Từ Android 12, báo thức chính xác yêu cầu quyền SCHEDULE_EXACT_ALARM.

AlarmManager là gì?

AlarmManager là một dịch vụ hệ thống Android cung cấp API để lên lịch tác vụ với thời gian thực thi chính xác hoặc xấp xỉ. Nó đã tồn tại từ phiên bản Android đầu tiên và vẫn là cách đáng tin cậy duy nhất để thực thi mã tại một thời điểm cụ thể, bất kể trạng thái của ứng dụng và thiết bị.

Nguyên lý hoạt động rất đơn giản: ứng dụng gửi đến hệ thống một PendingIntent với thời gian kích hoạt đã chỉ định. Khi đến thời gian đã chỉ định, hệ thống gửi Intent đến một BroadcastReceiver đã đăng ký hoặc khởi động Service. Ngay cả khi thiết bị ở chế độ ngủ, WakeLock cho phép bộ xử lý thức dậy và xử lý sự kiện.

Lĩnh vực ứng dụng chính của AlarmManager là các tác vụ yêu cầu thời gian chính xác: báo thức, lời nhắc lịch, khởi động các thao tác dài tại một giờ cụ thể. Đối với các tác vụ mà độ chính xác không quan trọng (đồng bộ hàng ngày), Google khuyên dùng WorkManager hoặc JobScheduler vì chúng tiết kiệm năng lượng hơn.

AlarmManager hoạt động như thế nào?

AlarmManager nhận PendingIntent và thời gian kích hoạt từ ứng dụng. Hệ thống lưu yêu cầu này vào bộ lập lịch nội bộ và đánh thức bộ xử lý tại thời gian đã chỉ định để gửi Intent. Nhà phát triển phải đăng ký BroadcastReceiver trước để xử lý Intent này.

Các loại báo thức

AlarmManager hỗ trợ 4 loại báo thức: ELAPSED_REALTIME (thời gian từ khi khởi động, không đánh thức), RTC (thời gian thực, không đánh thức), ELAPSED_REALTIME_WAKEUP (thời gian từ khi khởi động, đánh thức thiết bị) và RTC_WAKEUP (thời gian thực, đánh thức). Các phiên bản WAKEUP cần thiết nếu tác vụ phải thực thi ngay cả khi thiết bị đang ngủ.

LoạiThời gianĐánh thứcVí dụ
ELAPSED_REALTIMEtừ lúc khởi độngkhôngbộ đếm thời gian hoạt động
RTCdấu thời gian Unixkhôngghi nhật ký
ELAPSED_REALTIME_WAKEUPtừ lúc khởi độngtác vụ định kỳ
RTC_WAKEUPdấu thời gian Unixbáo thức

Quyền và sự cho phép

Từ Android 12 (API 31), việc sử dụng báo thức chính xác (setExact) yêu cầu quyền SCHEDULE_EXACT_ALARM. Người dùng có thể thu hồi quyền này qua cài đặt. Đối với các ứng dụng cần báo thức chính xác có hiển thị (ví dụ: ứng dụng đồng hồ), USE_EXACT_ALARM được sử dụng, quyền này được cấp khi cài đặt.

Các phương thức set, setRepeating và setExact

AlarmManager cung cấp ba phương thức chính để lên lịch tác vụ. Việc chọn phương thức sẽ quyết định độ chính xác kích hoạt và tác động đến mức tiêu thụ điện năng của thiết bị.

set — phương thức cơ bản cho một lần kích hoạt không chính xác. Hệ thống có thể dịch chuyển thời gian lên đến vài phút để nhóm với các sự kiện khác. Phù hợp cho các tác vụ mà độ chính xác không quan trọng: lời nhắc mở ứng dụng.

setRepeating — phương thức cho các lần lặp định kỳ. Từ Android 4.4 (API 19), setRepeating đã trở nên không chính xác — khoảng thời gian có thể thay đổi. Hệ thống không còn đảm bảo một khoảng thời gian cố định. Thay vì setRepeating, nên sử dụng setExact với lên lịch lại hoặc WorkManager với PeriodicWorkRequest.

setExact — phương thức cho một lần kích hoạt chính xác. Hệ thống đánh thức thiết bị càng gần thời gian đã chỉ định càng tốt. setAlarmClock là một trường hợp đặc biệt của setExact, cũng hiển thị biểu tượng báo thức trên thanh trạng thái và có mức ưu tiên cao nhất trong tất cả các loại báo thức.

kotlin
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager

// Báo thức chính xác một lần
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
    this, 0, intent,
    PendingIntent.FLAG_IMMUTABLE
)

alarmManager.setAlarmClock(
    AlarmManager.AlarmClockInfo(
        targetTime, pendingIntent
    ),
    pendingIntent
)

Ví dụ sử dụng AlarmManager

Một kịch bản điển hình là tạo lời nhắc hàng ngày vào một thời gian cụ thể. RTC_WAKEUP với setExact được sử dụng cho mục đích này. Khi được kích hoạt, BroadcastReceiver khởi chạy thông báo hoặc Service. Sau khi xử lý, tác vụ phải được lên lịch lại cho ngày hôm sau.

kotlin
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("Lời nhắc")
            .setContentText("Đến lúc hoàn thành tác vụ")
            .setSmallIcon(R.drawable.ic_reminder)
            .build()

        notificationManager.notify(1001, notification)
    }
}

Để lặp lại hàng ngày, setExact được sử dụng với tính toán thời gian kích hoạt tiếp theo. Cờ có thể được truyền trong Intent để xác định các loại lời nhắc khác nhau. Đảm bảo BroadcastReceiver được đăng ký trong AndroidManifest.xml với xử lý hành động WAKEUP.

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

Tối ưu hóa và khuyến nghị

AlarmManager là một công cụ mạnh mẽ nhưng tiêu tốn nhiều năng lượng. Mỗi báo thức WAKEUP đưa thiết bị ra khỏi chế độ ngủ, tiêu thụ pin. Google khuyên nên giảm thiểu việc sử dụng báo thức chính xác và ưu tiên setExactAndAllowWhileIdle trên Android 6+ để giảm tác động đến Doze Mode. Đối với các tác vụ định kỳ không yêu cầu độ chính xác, hãy sử dụng WorkManager với PeriodicWorkRequest, không cần đánh thức thiết bị và không làm hao pin mỗi lần thực thi.

Kiểm tra AlarmManager trong kiểm thử đơn vị

Để kiểm tra AlarmManager, hãy sử dụng TestAlarmManager từ Android Test Framework. Nó cho phép mô phỏng kích hoạt báo thức mà không cần chờ thời gian thực. Robolectric cung cấp ShadowAlarmManager, chặn các cuộc gọi set, setExact và setRepeating, cung cấp các phương thức để kích hoạt cưỡng chế và kiểm tra số lượng tác vụ đã lên lịch. Đối với kiểm thử đơn vị của BroadcastReceiver, hãy sử dụng Robolectric.getForegroundScheduler(). Các kiểm thử Espresso với IdlingResource chờ kích hoạt báo thức trong kiểm thử tích hợp cũng có sẵn.

Di chuyển từ AlarmManager sang WorkManager

Nếu ứng dụng của bạn sử dụng AlarmManager cho các tác vụ định kỳ không yêu cầu thời gian chính xác, hãy cân nhắc di chuyển sang WorkManager. PeriodicWorkRequest với khoảng thời gian tối thiểu 15 phút thay thế setRepeating, trong khi WorkManager đảm bảo thực thi sau khi khởi động lại, xử lý Doze Mode và không yêu cầu quyền SCHEDULE_EXACT_ALARM. Đối với các tác vụ quan trọng về thời gian (báo thức lúc 7 giờ sáng), AlarmManager vẫn là lựa chọn đúng đắn duy nhất. Chiến lược tối ưu là chỉ sử dụng AlarmManager cho báo thức với setAlarmClock và chuyển tất cả các tác vụ nền khác sang WorkManager.

Đối với các tác vụ định kỳ không yêu cầu độ chính xác, hãy sử dụng WorkManager với PeriodicWorkRequest. Đối với các tác vụ có thời gian chính xác nhưng không quan trọng phải kích hoạt ở chế độ ngủ — hãy sử dụng setExact mà không có WAKEUP. Và chỉ cho các báo thức cần đánh thức bắt buộc — hãy sử dụng setAlarmClock hoặc RTC_WAKEUP.

Điều quan trọng nữa là kiểm tra quyền SCHEDULE_EXACT_ALARM trên Android 12+. Nếu quyền không được cấp, setExact sẽ hoạt động như set thông thường (không chính xác). Sử dụng AlarmManager.canScheduleExactAlarms() để kiểm tra. Nếu thiếu quyền, bạn có thể yêu cầu người dùng vào cài đặt qua Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM).

Xử lý BOOT_COMPLETED để khôi phục báo thức

Một tính năng cực kỳ quan trọng của AlarmManager — tất cả các báo thức đã lên lịch đều bị đặt lại sau khi khởi động lại thiết bị. Để khôi phục chúng, bạn phải khai báo BroadcastReceiver xử lý Intent.ACTION_BOOT_COMPLETED và lên lịch lại tất cả các báo thức đang hoạt động trong phương thức onReceive. Nếu không làm điều này, người dùng sẽ mất tất cả lời nhắc sau khi tắt và bật điện thoại.

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

Trong thực tế, AlarmManager vẫn là giải pháp tốt nhất cho các ứng dụng báo thức, lịch, nhắc nhở uống thuốc và bất kỳ tác vụ nào mà thời gian thực thi quan trọng đối với người dùng. Đối với tất cả các kịch bản công việc nền khác, WorkManager hoặc JobScheduler được ưu tiên hơn.

Khi chọn giữa AlarmManager và WorkManager, hãy tuân theo quy tắc này: nếu người dùng yêu cầu rõ ràng nhắc nhở lúc 2:30 chiều — hãy sử dụng AlarmManager với setAlarmClock. Nếu tác vụ nên thực thi “khoảng một lần mỗi giờ” — WorkManager với PeriodicWorkRequest sẽ tiết kiệm năng lượng và đáng tin cậy hơn.

Các câu hỏi thường gặp

Sự khác biệt giữa setExact và setAlarmClock là gì?

Cả hai phương thức đều đảm bảo kích hoạt chính xác, nhưng setAlarmClock còn hiển thị biểu tượng báo thức trên thanh trạng thái và thông báo cho hệ thống rằng đó là báo thức của người dùng. Trên Android 6+, setAlarmClock có khả năng miễn nhiễm với Doze Mode, trong khi setExact có thể bị trì hoãn.

AlarmManager hoạt động như thế nào sau khi khởi động lại thiết bị?

Sau khi khởi động lại, tất cả các báo thức đã lên lịch đều bị đặt lại. Để khôi phục chúng, bạn phải đăng ký BroadcastReceiver cho hành động BOOT_COMPLETED và lên lịch lại tất cả các tác vụ trong onReceive. Nếu không làm điều này, sẽ không có báo thức nào kích hoạt sau khi bật thiết bị.

Tại sao setRepeating không được khuyến nghị trên Android 4.4+?

Từ API 19, setRepeating đã trở nên không chính xác — hệ thống có thể dịch chuyển khoảng thời gian để tiết kiệm năng lượng. Thay vào đó, hãy sử dụng setExact với lên lịch lại thủ công hoặc WorkManager với PeriodicWorkRequest, cung cấp hành vi dự đoán trước hơn.

Cần quyền gì cho báo thức chính xác trên Android 12+?

Đối với setExact, cần có quyền SCHEDULE_EXACT_ALARM, người dùng có thể cấp hoặc thu hồi trong cài đặt. Đối với setAlarmClock có hiển thị giao diện đồng hồ, USE_EXACT_ALARM được sử dụng, quyền này được cấp tự động khi cài đặt từ cửa hàng.

Có thể sử dụng AlarmManager mà không cần PendingIntent không?

Không, AlarmManager luôn hoạt động thông qua PendingIntent. Nó có thể là PendingIntent.getBroadcast cho BroadcastReceiver, PendingIntent.getService cho Service hoặc PendingIntent.getActivity cho Activity. Không có PendingIntent, hệ thống không thể gửi sự kiện đến ứng dụng.

Tổng kết

  • AlarmManager là dịch vụ hệ thống Android để thực thi tác vụ vào thời gian chính xác với khả năng đánh thức thiết bị.
  • Bốn loại báo thức — ELAPSED_REALTIME, RTC, ELAPSED_REALTIME_WAKEUP và RTC_WAKEUP — bao phủ các kịch bản khác nhau.
  • setExact và setAlarmClock là các phương thức duy nhất để kích hoạt chính xác trên các phiên bản Android hiện đại.
  • setRepeating đã lỗi thời trên Android 4.4+ — hãy sử dụng setExact với lên lịch lại thủ công.
  • Quyền SCHEDULE_EXACT_ALARM là bắt buộc trên Android 12+ cho báo thức chính xác.
  • WorkManager hoặc JobScheduler được ưu tiên hơn cho các tác vụ nền không chính xác không yêu cầu thời gian.
  • Đừng quên xử lý BOOT_COMPLETED để khôi phục báo thức sau khi khởi động lại thiết bị.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm