How Android alarms actually work (AlarmManager, Doze, and OEM task killers)

If you've ever wondered why some alarm apps silently fail on some phones, the answer lives in Android's alarm-scheduling stack. Here's how it actually works, and the choices RiseProof makes at each layer.

The AlarmManager hierarchy

Android's AlarmManager offers several ways to schedule future work, and they are not equal:

  • set() / setInexactRepeating() — batched and deferred at the system's convenience. Fine for "sync sometime tonight," useless for alarms.
  • setExact() — fires at the requested time, but is still deferred inside Doze's maintenance windows.
  • setExactAndAllowWhileIdle() — exact and Doze-resistant, but rate-limited (roughly one alarm per app per 9 minutes in idle), which the docs explicitly say is not for user-facing alarm clocks.
  • setAlarmClock() — the first-class citizen. The system treats it as a real, user-visible alarm clock: it shows in the status bar, it exempts the app from Doze restrictions ahead of the fire time, and it fires exactly even in deep idle.

RiseProof uses setAlarmClock(), full stop. It is the only API whose contract matches what a user means by "alarm." On Android 12+ this pairs with the SCHEDULE_EXACT_ALARM / USE_EXACT_ALARM permissions; alarm-clock apps qualify for the latter, which can't be silently revoked.

Doze and App Standby

Since Android 6, a stationary, screen-off phone descends into Doze: network is cut, jobs and syncs are batched into rare maintenance windows, and ordinary alarms are deferred. App Standby buckets (Android 9+) further throttle apps you rarely open. This is the graveyard of naive alarm implementations — a setExact() alarm can fire many minutes late at 6am, which is the same as not firing.

setAlarmClock() cuts through all of it by design. That's not a hack; it's the platform's own definition of what an alarm clock is entitled to.

Reboots, updates, and the alarm database

Scheduled alarms do not survive a reboot — the OS forgets them. A real alarm app must persist its alarms in a local database, listen for BOOT_COMPLETED (and MY_PACKAGE_REPLACED after app updates, and time/timezone-change broadcasts), and re-register everything. RiseProof stores alarms in a local database on your phone and re-registers on every one of those events. Recurrence (weekday patterns, one-off alarms, DST transitions) is computed locally with timezone-aware logic — there is no server that can get your Tuesday wrong.

The OEM problem

Some manufacturers ship aggressive "battery optimizers" that force-stop backgrounded apps in ways stock Android never would — killing their scheduled alarms with them. No app can code its way around a vendor force-stop. What an honest app can do: use setAlarmClock() (the most protected primitive), detect the affected manufacturers, and walk you through the vendor-specific whitelist screens during setup. RiseProof does exactly that, and its reliability checklist tells you plainly if a needed permission or exemption is missing — before the morning it matters, not after.

The takeaway

Alarm reliability on Android isn't magic and isn't luck. It's choosing the right primitive, persisting state, handling the boring broadcasts, and being upfront with users about the two or three things only they can configure. That's the entire engineering philosophy behind RiseProof, and it's why we're comfortable being technical about it in public.

Earn your silence.

Tomorrow morning is day one.

Coming soon to Android and iOS. One payment. Every mission. Yours for good. One email at launch — early access comes from this list.

Or get an email when new missions and features land:

No spam, ever. Unsubscribe anytime.

Coming soon to theApp StoreComing soon toGoogle Play