DEV Community

Clean Labs
Clean Labs

Posted on

What I Learned Building Reliable Android Reminders

Building a task app with reminders taught me something I didn't fully appreciate at the beginning:

A reminder is not a single Android feature. It is a chain of systems that all have to work together.

The user sees one simple thing:

"Remind me at 3 PM."

Behind that, Android may be dealing with alarms, background execution, battery restrictions, notification permissions, notification channels, device-specific behavior, and time zones.

After working through these problems while building Wumilo, I started thinking about reminder reliability very differently.

A reminder is a chain, not an API call

It is tempting to think about reminders as:

task time → alarm → notification
Enter fullscreen mode Exit fullscreen mode

In reality, there are several points where things can go differently from what the user expects:

User creates reminder
        ↓
App stores the reminder
        ↓
App schedules the system event
        ↓
Android decides when the event can run
        ↓
The app handles the event
        ↓
Android delivers the notification
        ↓
Notification settings determine how it is presented
Enter fullscreen mode Exit fullscreen mode

That distinction matters when debugging.

If a reminder doesn't appear, the problem isn't necessarily the scheduling code.

The alarm may have been scheduled correctly while the notification was blocked.

Or the notification may be configured correctly while Android delayed background activity.

Or everything may work normally until the phone enters a deeper idle state.

Once I started looking at reminders as a delivery chain, debugging became much more useful.

Exact alarms solve one part of the problem

One of the first Android concepts that becomes important when building time-sensitive reminders is the exact alarm system.

An exact alarm is about when Android should trigger a scheduled event.

That is important for something like:

"Remind me at 3:00 PM."

But an exact alarm does not automatically guarantee that the user will see a notification at 3:00 PM.

There are still other parts of the system involved.

Notification permission, notification channels, Do Not Disturb, lock-screen settings, and device-specific restrictions can all affect what the user experiences.

I wrote a separate explanation of this distinction here:

Understanding exact alarms and Android reminders

The important lesson for developers is simple:

Precise scheduling and successful notification delivery are related, but they are not the same problem.

Battery optimization is another layer

Android's power-management features make sense from the phone's perspective.

A phone that allows every application to run freely in the background would waste battery quickly.

The challenge is that a reminder application is specifically asking the operating system to do something later.

That creates a tension between:

  • saving battery
  • limiting background activity
  • running scheduled work
  • delivering time-sensitive events

Doze and App Standby are part of Android's power-management model, while some manufacturers add their own restrictions on top.

This means two phones running the same Android application can behave differently.

A developer can have a reminder that works perfectly during development and still receive reports from users whose devices handle background activity more aggressively.

That's why I stopped treating battery optimization as a simple "bug."

It is often part of the environment in which the application is running.

I documented the Android side of this separately:

How battery optimization can delay Android reminders

Samsung made the problem even more interesting

Testing on one Android phone is not enough.

Samsung devices have their own battery-management behavior and settings around apps that can be put to sleep.

That can be especially relevant for applications that need to do something later without the user actively opening them.

This was one reason I ended up separating general Android battery behavior from Samsung-specific guidance.

The general Android concepts are useful everywhere.

The device-specific settings are not.

For developers, this is a good reminder that "Android" isn't always a single environment in practice.

An application can use the same APIs while the surrounding system behavior differs between manufacturers and device configurations.

For the Samsung-specific side, I keep a separate guide:

Samsung Sleeping Apps and Android Reminders

Notifications are a separate failure point

Another lesson was not to assume that an alarm and a notification are the same thing.

Modern Android has its own notification system, including:

  • notification permissions
  • notification channels
  • notification importance
  • Do Not Disturb and other interruption controls
  • lock-screen notification settings
  • device-specific notification controls

Android 13 also introduced the POST_NOTIFICATIONS runtime permission for many apps.

So when someone says:

"My reminder didn't show."

There are several questions worth asking.

Did the scheduled event happen?

Did the application handle it?

Was a notification created?

Was the notification channel enabled?

Does the app have notification permission?

Was the phone suppressing or hiding the notification?

Those questions lead to much better debugging than simply checking whether the reminder was saved.

Time zones turned out to be a product problem

Time zones were another area where the technical details quickly became product decisions.

Suppose someone creates a reminder for 9:00 AM and then travels somewhere in a different time zone.

What should happen?

There isn't one universally correct answer.

A reminder can represent a particular instant in time, or it can represent a local clock time that should follow the user.

Those are different concepts.

For a task application, the expected behavior matters more than simply converting a timestamp.

This is why time-zone handling needs to be considered part of the reminder model, not just something added to date formatting later.

I ended up documenting the behavior separately because it is easy to overlook until users actually travel:

Android Reminders and Time Zones

Restarting the phone is an important test

One of the simplest tests is also one of the easiest to forget.

Create a reminder.

Restart the phone.

Wait for the reminder.

It sounds obvious, but rebooting changes the lifecycle of the application and the Android environment.

For a reminder app, I also want to think about scenarios such as:

  • the app hasn't been opened for a while
  • the screen is locked
  • the device is idle
  • battery-saving features are active
  • notifications have been restricted
  • the device has been restarted
  • the user changes time zones
  • the user changes notification settings
  • the reminder is scheduled far into the future

A reminder system isn't really finished when it works immediately after pressing "Save."

It needs to work when the application isn't currently in front of the user.

Testing the whole delivery chain

This changed how I think about testing reminder features.

A unit test can tell me that a reminder time was calculated correctly.

It cannot fully reproduce what happens when Android, the device manufacturer, battery management, and notification settings all get involved.

So I find it useful to think about testing in layers.

Application layer

Does the task store the correct reminder information?

Does editing or deleting the task update the scheduled reminder correctly?

Scheduling layer

Was the system event scheduled for the expected time?

What happens when the reminder is changed?

What happens when it is deleted?

Device layer

What happens during idle?

What happens after reboot?

What happens when battery restrictions are enabled?

Notification layer

Does the notification appear?

Is the notification channel enabled?

What happens when notification permission is denied?

Time layer

What happens when the device time zone changes?

What happens when daylight-saving rules are involved?

The more layers I tested, the more obvious it became that "the reminder code works" isn't the same as "the reminder feature works."

Don't solve everything by telling users to disable battery optimization

There is also a temptation to make troubleshooting simple:

"Disable every battery restriction."

That can sometimes make a particular problem disappear, but it isn't a great universal solution.

Battery management exists for a reason.

Users shouldn't have to turn their phone into a permanently unrestricted environment just to use a task app.

A better approach is to understand which restriction is actually relevant, explain what it can affect, and give users targeted guidance when necessary.

That also makes support documentation more useful.

Instead of:

"Android is killing the app."

You can explain what the relevant Android or manufacturer setting does and why changing it may help.

The biggest lesson: reliability is partly a UX problem

The most interesting thing I learned is that reminder reliability isn't purely an engineering problem.

It is also a communication problem.

The user doesn't care which Android subsystem caused the failure.

They care that they asked their phone to remind them about something and whether they can trust it.

That means a reminder app needs more than scheduling code.

It needs:

  • sensible defaults
  • predictable behavior
  • useful diagnostics
  • clear settings
  • good testing
  • honest limitations
  • troubleshooting guidance that matches the actual device

The more complicated the operating system becomes, the more important that last part gets.

What I would do differently on a new reminder project

If I were starting another reminder application today, I would think about reliability much earlier.

I'd define the reminder lifecycle before implementing the UI:

Create
  ↓
Persist
  ↓
Schedule
  ↓
Survive lifecycle changes
  ↓
Trigger
  ↓
Notify
  ↓
Verify / troubleshoot
Enter fullscreen mode Exit fullscreen mode

I'd also test on more than one Android device and treat manufacturer-specific behavior as something to investigate rather than something to assume away.

Most importantly, I'd avoid designing the system around the assumption that one Android API controls the entire experience.

It doesn't.

A practical checklist for developers

Before calling a reminder feature "done," I'd want to be able to answer these questions:

  • Is the reminder stored reliably?
  • Is the scheduled time calculated correctly?
  • Does the scheduling mechanism match the precision the feature requires?
  • What happens when the device is idle?
  • What happens after a reboot?
  • What happens under battery restrictions?
  • What happens on manufacturer-customized Android versions?
  • Does the app have the notification access it needs?
  • Are notification channels configured correctly?
  • What happens when notifications are suppressed?
  • What happens when the user changes time zones?
  • Can users understand what to check when something goes wrong?

If several of those answers are unknown, the reminder system probably isn't finished yet.

Final takeaway

Building reliable Android reminders changed my mental model of the feature.

I started with something that looked simple:

Schedule something for later.
Enter fullscreen mode Exit fullscreen mode

I ended up with something closer to:

Store the user's intention
        ↓
Schedule it at the right time
        ↓
Work within Android's power-management model
        ↓
Handle the device lifecycle
        ↓
Trigger the event
        ↓
Deliver a notification
        ↓
Make the result visible to the user
Enter fullscreen mode Exit fullscreen mode

That is a much bigger system.

And that is probably the most useful lesson I've taken from building Wumilo:

When a mobile feature depends on something happening later, don't test only whether you can schedule it. Test whether the entire chain can deliver it.

Top comments (0)