2026'da güvenilir Android hatırlatıcıları: WorkManager, kesin alarmlar ve yeni pil kuralları
2026'da Android'de gerçekten tetiklenen hatırlatıcılar nasıl yayınlanır — WorkManager mı AlarmManager mı, SCHEDULE_EXACT_ALARM, POST_NOTIFICATIONS ve hâlâ can yakan OEM tuhaflıkları.
Android’de bir hatırlatıcı uygulaması, ancak hatırlatıcı görünürse çalışır. Kulağa apaçık geliyor — ta ki birini yayınlayana kadar. Sonra doze modunu, uygulama bekleme kovalarını (app standby buckets), OEM pil optimize edicilerini, SCHEDULE_EXACT_ALARM iznini, POST_NOTIFICATIONS çalışma zamanı iznini, ön plan servisi kısıtlamalarını ve Samsung ile Xiaomi’nin, ne kadar doğru yazmış olursan ol, “pil tasarrufu” için zamanlanmış işinizi sessizce öldüreceği o güzel gerçeği keşfediyorsunuz.
Bütün değer önerisi “beni doğru zamanda, nazikçe hatırlat” olan bir su takip uygulaması olan Hydrame’i geliştirdim. Android hatırlatıcı yığınını güvenilirliğe zorlamak için itiraf etmek istediğimden daha fazla zaman harcadım. Bu yazı, sonunda işe yarayan oyun kitabının 2026 sürümü.
Tek paragrafta hatırlatıcı sorunu
Android arka plan işlerini öldürmede agresiftir ve öyle de olmalı — kontrolsüz bırakılırsa her uygulama birkaç dakikada bir telsizi uyandırır ve piliniz öğle yemeğine kadar biterdi. Meşru hatırlatıcı uygulamaları için sonuç, her biri sürümler ve OEM arayüzleri arasında biraz farklı davranan, üst üste binen bir API yığını olur. İş, sizin “kesin olmalı” seviyeniz için doğru ilkel yapıyı seçmek ve geri kalanın gerçek cihazlarda test etmek olduğunu kabul etmektir.
2026’da önemli olan iki ilkel yapı şunlardır:
WorkManager— kesin olmayan, ertelenebilir işler için. Periyodik kontroller, “bana önümüzdeki bir saat içinde bir ara hatırlat” kullanım durumları. Pil bilinçli, birleştirilir, yeniden başlatmalardan sonra bile çalışır.AlarmManager.setExactAndAllowWhileIdle— belirli bir zamanda kesin kullanıcı tarafından görülebilen bildirimler için. Pahalı olanı. İdareli kullanın ve yalnızca “15 dakika kayması” özelliği bozuk hissettirecekse.
Hatırlatıcınız tam olarak 19:30’da tetiklenmek zorundaysa, kesin bir alarma ihtiyacınız var. “19:30 civarında bir ara” yeterliyse, WorkManager kullanın. Çoğu uygulama varsayılan olarak yanlış olanı seçer.
Doğru yapmanız gereken üç izin
2026’da üç çalışma zamanı/kurulum izni, kullanıcının bir hatırlatıcıyı görüp görmeyeceğine karar verir:
POST_NOTIFICATIONS(çalışma zamanı, Android 13+). Bu olmadan bildiriminiz kelimenin tam anlamıyla görünmez. Doğru anda isteyin, ilk açılışta değil.SCHEDULE_EXACT_ALARM(Android 12+, 13+‘da kısıtlı).setExactAndAllowWhileIdleiçin gereklidir. Android 14+‘da bu, yalnızca kullanıcı sistem ayarlarında açıkça etkinleştirdikten sonra verilir; uygulamanın kullanıcıyı oraya göndermesi gerekir.USE_EXACT_ALARM(Android 13+, özel kullanım). Kesin alarmların çekirdek olduğu uygulamalar için (çalar saatler, takvim hatırlatıcıları, su takibi). Play gerekçe ister.
Hydrame manifestosu şöyle görünüyor:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
RECEIVE_BOOT_COMPLETED, çoğu kişinin unuttuğu izindir — bu olmadan, zamanlanmış alarmlarınız bir sonraki yeniden başlatmada kaybolur. ACTION_BOOT_COMPLETED üzerinde bir BroadcastReceiver’dan yeniden zamanlayın.
POST_NOTIFICATIONS iznini doğru anda isteme
İlk açılışta istemeyin. Değerle eşleşen bir anda isterseniz kabul oranı çarpıcı biçimde daha yüksek olur: tam olarak kullanıcı ilk hatırlatıcısını etkinleştirdiğinde. Gerçek bir akış:
@Composable
fun EnableReminderButton(onEnabled: () -> Unit) {
val context = LocalContext.current
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
) { granted ->
if (granted) onEnabled()
}
FilledButton(onClick = {
if (Build.VERSION.SDK_INT >= 33) {
val state = ContextCompat.checkSelfPermission(
context,
Manifest.permission.POST_NOTIFICATIONS,
)
if (state == PackageManager.PERMISSION_GRANTED) onEnabled()
else launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
} else {
onEnabled()
}
}) { Text("Enable reminders") }
}
Her zaman yaptığım iki şey daha:
- İkinci şans gerekçesi. Kullanıcı reddederse, hemen tekrar sormayın. Bir sonraki sefer hatırlatıcıyı etkinleştirmeye çalıştığında, kendisinin değiştirebilmesi için uygulamanın ayarlar ekranını açan bir düğmeyle birlikte küçük bir satır içi mesaj gösterin.
- “Bir daha sorma” ile reddedilen durumu tespit edin; son reddi DataStore’da hatırlayarak —
shouldShowRequestPermissionRationalebunun için tek başına güvenilmezdir.
Kesin olmayan: WorkManager periyodik iş
“Sabahın bir ara” kabul edilebilir olduğu bir hatırlatıcı için WorkManager, sıkıcı doğru cevaptır:
class DailyHydrationCheckWorker(
appContext: Context,
params: WorkerParameters,
) : CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
scheduleTodayReminders()
return Result.success()
}
}
fun scheduleDailyHydrationCheck(context: Context) {
val request = PeriodicWorkRequestBuilder<DailyHydrationCheckWorker>(
repeatInterval = 1, repeatIntervalTimeUnit = TimeUnit.DAYS,
)
.setConstraints(
Constraints.Builder()
.setRequiresBatteryNotLow(true)
.build(),
)
.setInitialDelay(secondsUntil(6, 0).toLong(), TimeUnit.SECONDS)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"daily_hydration_check",
ExistingPeriodicWorkPolicy.UPDATE,
request,
)
}
İnsanların canını yakan birkaç şey:
- 15 dakikalık asgari periyot.
PeriodicWorkRequest, ne istediğinizden bağımsız olarak 15 dakikada bir daha sık çalışmaz. 15 dakikadan kısa zamanlama için kendini zincirleyen tek seferlik iş kullanın. - Kesin zamanlama yok. WorkManager bir pencere içinde zamanlar. “Tam 8:00:00’da” istiyorsanız, bu yanlış ilkel yapıdır.
- Battery-not-low hem kullanıcılarınıza hem de sisteme dosttur; aksi için bir nedeniniz yoksa açın.
Kesin: AlarmManager.setExactAndAllowWhileIdle
Hatırlatıcı belirli bir anda tetiklenmek zorundaysa — örneğin, bir kullanıcı “beni 19:30’da hatırlat” dediyse ve bunu ciddiye alıyorsa — kesin bir alarma ihtiyacınız var. Desen:
fun scheduleExactReminder(
context: Context,
triggerAtMillis: Long,
requestCode: Int,
) {
val am = context.getSystemService(AlarmManager::class.java)
if (Build.VERSION.SDK_INT >= 31 && !am.canScheduleExactAlarms()) {
// Send the user to the system page to grant the permission.
context.startActivity(
Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM)
.setData(Uri.parse("package:${context.packageName}"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
)
return
}
val intent = Intent(context, ReminderReceiver::class.java)
.putExtra("requestCode", requestCode)
val pending = PendingIntent.getBroadcast(
context, requestCode, intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pending)
}
setExactAndAllowWhileIdle, doze’a saygı gösterendir. setAlarmClock’u yalnızca uygulamanız gerçekten bir çalar saatse kullanın — sistem arayüzünde bir sonraki alarm çipini gösterir ve en yüksek önceliği alır.
Ağır an için alıcı + ön plan servisi
Alarm tetiklendiğinde, bir bildirim göndermek için birkaç saniyelik uyanık zamanınız olur. Basit bir “ding!” hatırlatıcısı için bu yeterlidir:
class ReminderReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Post the notification synchronously.
val nm = context.getSystemService(NotificationManager::class.java)
nm.notify(
intent.getIntExtra("requestCode", 0),
buildHydrationNotification(context),
)
// Re-schedule the next one.
scheduleNext(context)
}
}
Alarmda gerçek iş yapmanız gerekiyorsa (senkronizasyon, indirme), hemen bir ön plan servisine yükseltin. Zeki olmaya çalışmayın — alıcıda takılırsanız sistem sizi bir anda iptal eder.
Yeniden başlatmalar ve saat dilimi değişiklikleri
İki olay, saf bir uygulamayı sessizce bozar:
- Yeniden başlatma. Alarmlar silinir.
ACTION_BOOT_COMPLETED’ı dinleyin ve kalıcı durumunuzdan yeniden zamanlayın. - Saat dilimi değişikliği. Sabah 7’lik bir hatırlatıcı, kullanıcı taşınmadan önce yerel saatle 7’de ve taşındıktan sonra İstanbul saatiyle 7’de tetiklenmemelidir.
ACTION_TIMEZONE_CHANGED’ı dinleyin ve yeniden hesaplayın.
Tek bir alıcı ikisini de halleder:
<receiver android:name=".BootAndTimezoneReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
MY_PACKAGE_REPLACED, uygulama güncellemelerinin tetiklediğidir — kodunuz tazedir, ancak alarmlarınız gitmiştir. Orada da yeniden zamanlayın.
OEM optimize ediciler — sessiz katiller
2026’da kalan en kötü suçlu hâlâ Samsung’un “Uyuyan uygulamalar” listesi, Xiaomi’nin otomatik başlatma ve pil tasarrufu ise hemen arkasında. İki pratik savunma:
- Uygulama içi tanılama afişi. Kullanıcının hatırlatıcıları etkinken 24 saat içinde bildirim tetiklenmediyse, doğru OEM ayarlar sayfasına “Bunu düzelt” derin bağlantısı içeren küçük bir afiş gösterin. Stack Overflow ve Don’t Kill My App projesi derin bağlantıları güncel tutar; bunları yerel olarak önbelleğe alın.
- Pil beyaz listesini hevesle istemeyin. Kullanıcıları korkutur ve Play bundan hoşlanmaz. Bunu, zaten kaçırılmış bir hatırlatıcı görmüş kullanıcı için saklayın.
Sonunda işe yarayan desen
Hydrame üzerinde üç yinelemeden sonra, sonunda güvenilir hissettiren mimari:
- Bir periyodik
WorkManagerişi her gece çalışır. Kullanıcının programını okur ve sonraki 24 saatin kesin alarmlarını ekler. - Her kesin alarm, bir
BroadcastReceiveraracılığıyla bir bildirim gönderir. Alıcı aptaldır — veritabanı çağrısı yok, ağ yok. - Yeniden başlatma + saat dilimi değişikliği + uygulama güncelleme alıcıları, programı yeniden oluşturmak için aynı gecelik işi manuel olarak tetikler.
- Bir kalp atışı metriği (DataStore’da saklanan son başarılı bildirim zaman damgası), uygulama içi “hatırlatıcılarınız telefonunuz tarafından öldürülebilir” afişini besler.
Bu, ilk içgüdüme güvenseydim (“sadece WorkManager kullan”) yazacağımdan daha fazla bağlantı işi. Ama her parça, o olmadan bir şey sessizce bozulduğu için var.
Yine gerçek telefonlarda test etme
Yazdığım her Android yazısından aynı cümleyi tekrarlayacağım: güvenilir hatırlatıcıları yalnızca emülatörde test edemezsiniz. Ucuz bir Samsung, ucuz bir Xiaomi ve bir Pixel edinin. Şu andan 30 dakika sonrasına bir hatırlatıcı kurun. Telefonu kilitleyin ve masanın üstünde bırakın. Geri gelin ve neyin tetiklendiğini, neyin tetiklenmediğini görün. O tek deney, herhangi bir blog yazısından daha değerlidir.
Bu dahil. Git test et.
// İlgili okumalar
Günlükten dahası
Android bildirim eylemleri doğru şekilde: uygulamayı açmadan bir dozu alındı olarak işaretlemek
Android bildirim eylem düğmeleri için pratik bir rehber — PendingIntent'ler, trambolin kısıtlaması, goAsync() ve Room durumunu güvenle güncellemek.
Gerçekten uyacağın bir ilaç rutini kurmak
İlaç uyumuna dair pratik bir rehber — insanlar dozları neden kaçırır, hatırlatıcı zamanlaması gerçekte nasıl işler ve kötü bir haftadan da sağ çıkan bir rutin nasıl kurulur.
İrade gücüne dayanmayan bir hidrasyon rutini
Çoğu hidrasyon tavsiyesi 'daha fazla su iç'e indirgenir ve aradaki boşluğu irade gücünün dolduracağını umar. İşte bunun yerine ipuçları ve nazik dürtmeler üzerine kurulu bir rutin.