Search code examples
androidservicetimerandroid-servicealarmmanager

Using a Service to create a timer that runs even if the app is minimized?


I seem to have a hard time getting a straight answer on this so I'll make a more pointed question.

I want to create a timer that is start/stop/pause/resettable. If the timer is active, it should continue to be active even if I go somewhere else in the app or minimize the app. If the app is destroyed / shut down / closed altogether then the timer can be shut down.

I looked into AlarmManager but it doesn't seem to work right on all devices. Would a Service be a viable alternative / do what I need it to do? What would I use to actually perform the counting? A sleep command in a loop that sends an update command back to a BroadcastReceiver?

How would I get it to send a notification to the user when the timer hits 0?


Solution

  • If the app is destroyed / shut down / closed altogether then the timer can be shut down.

    You seem to think that this is somehow different than "go somewhere else in the app or minimize the app". They are not. Either your process is running, or it is not, and your process can be terminated at any point in time when your UI is not in the foreground. A foreground Service, tied to a Notification, is a typical pattern for keeping a process around as long as possible, but this is not an absolute guarantee.

    Are you implying that on those devices, no matter what I do (Service, Timer, IntentService, AlarmManager, JobDispatcher, etc), they will kill the timer because those devices kill background tasks (unless I misunderstood the page)?

    There are two ways of doing scheduled work:

    • In-process: Timer, ScheduledExecutorService, postDelayed(), etc.

    • Out-of-process: AlarmManager, JobScheduler

    On all Android versions, when your process is terminated, any in-process timing goes away too. This is how most computers have worked, since the invention of the computer. Hence, these sorts of scheduling options are fine for cases where you only need the work to happen while your process is running (e.g., updating an on-screen elapsed-time counter).

    On Android 6.0+, AlarmManager and JobScheduler are affected by Doze mode and app standby. On previous versions, they are supposed to be generally reliable. However:

    • Some device manufacturers effectively created their own Doze mode equivalents, and those manufacturers might wipe out alarms and jobs as part of their power-savings initiatives

    • Nothing survives a force-stop, which normally happens only if the user clicks "Force Stop" on your app's screen in Settings, but on some devices happens more often (e.g., the manufacturer tied some sort of built-in "task manager" to have force-stop behavior)

    Hence, for devices where the manufacturer screwed around with Android, there may not be any form of reliable scheduling mechanism. In some cases, the manufacturers implementing precursors to Doze mode offered a whitelist mechanism, akin to how Doze mode does on Android 6.0+, where users could indicate apps that they would prefer not be impacted by the power-saving measures.