Giới thiệu
Bài này trùng lặp với bài 1003061556 (cùng code AlarmManager + BroadcastReceiver). Dưới đây là bản tóm tắt so sánh các phương pháp đặt lịch thông báo cục bộ hiện đại.
So sánh 3 phương pháp chính
| Tiêu chí | AlarmManager + BroadcastReceiver | WorkManager | Handler/Timer (trong Service) |
|---|---|---|---|
| Độ chính xác thời gian | Cao (giây) - setExactAndAllowWhileIdle | Thấp (cửa sổ 15p+) | Cao (nếu Service sống) |
| Sống sau reboot | Cần BOOT_COMPLETED receiver | Tự động | Không (Service bị kill) |
| Tiết kiệm pin | Thấp (wake lock) | Cao (JobScheduler) | Thấp |
| Phức độ code | Trung bình | Thấp | Thấp |
| Phù hợp cho | Báo thức, nhắc lịch chính xác | Sync dữ liệu, backup, log | Foreground service đang chạy |
Khuyến nghị chọn phương pháp
- Báo thức, nhắc uống thuốc, lịch hẹn chính xác: AlarmManager + setExactAndAllowWhileIdle() + BroadcastReceiver.
- Đồng bộ dữ liệu định kỳ, upload log, backup: WorkManager (PeriodicWorkRequest).
- Thông báo trong khi app đang chạy foreground: Handler.postDelayed() hoặc Coroutine delay.
Ví dụ WorkManager (Periodic)
// 1. Worker
public class DailyReminderWorker extends CoroutineWorker {
public DailyReminderWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}
@Override
public Result doWork() {
showNotification("Nhắc nhở hàng ngày", "Đến giờ uống nước!");
return Result.success();
}
// ... showNotification như cũ
}
// 2. Enqueue (chạy mỗi ngày vào 8h sáng)
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.NOT_REQUIRED)
.build();
PeriodicWorkRequest request = new PeriodicWorkRequest.Builder(DailyReminderWorker.class, 24, TimeUnit.HOURS)
.setInitialDelay(calculateDelayUntil8AM(), TimeUnit.MILLISECONDS)
.setConstraints(constraints)
.build();
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"daily_water_reminder", ExistingPeriodicWorkPolicy.KEEP, request);
Ví dụ AlarmManager cho báo thức chính xác
// Đặt báo thức 7:00 sáng mai
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 7);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_YEAR, 1);
}
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Kết luận
Đối với "Schedule local notification", hãy chọn:
- AlarmManager nếu cần độ chính xác cao (báo thức, reminder có giờ cố định).
- WorkManager nếu chỉ cần "khoảng lúc đó" và muốn tiết kiệm pin, bền vững qua reboot.