Search code examples
androidandroid-alarmsandroid-intentservice

Repeating IntentService using Timers- is it advisable?


I have an IntentService that downloads data from a server and I would like the IntentService to check for server updates at a certain interval. The following posts however advice against repeating a Service using a Timer - and instead emphasize on using an AlarmManager:

Why doesn't my Service work in Android? (I just want to log something ever 5 seconds)

Android - Service: Repeats only once

Android service stops

From Android's reference manual, an IntentService is described as:

IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

This "work queue processor" pattern is commonly used to offload tasks from an application's main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.

All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.

The part I don't really understand is why an IntentService (the posts have questions that are directed towards a Service and not an IntentService) is not allowed to execute repetitively using a Timer as it creates its own worker thread for execution. Is it permissible to use a Timer within an IntentService ? Or are AlarmManagers the only solution to periodically execute an IntentService ?

An explanation to this would be most appreciated .


Solution

  • Or are AlarmManagers the only solution to periodically execute an IntentService ?

    If you want it to work reliably, yes. Using AlarmManager is also much more friendly to the user.

    First, do not have a Service of any form running except when it is actively delivering value to the user. Watching the clock tick is not actively delivering value to the user. Having a Service running gives your process a bit higher priority than other processes, in terms of what processes get terminated to free up system RAM for future work. Having a Service around unnecessarily -- such as simply watching the clock tick -- hampers the user's ability to multitask well, as you tie up system RAM unnecessarily.

    This behavior will cause some users to attack you with task killers, such as swiping your app off the recent-tasks list. This will terminate your process, and therefore your Timer goes away too. Similarly, because too many sloppy developers keep their Service around for a long time, Android will automatically terminate such processes after some time, Service notwithstanding.

    Finally, usually one facet of "check for server updates at a certain interval" is that you want this work to occur even if the device goes into sleep mode. With your everlasting-service approach, that will require you to keep the CPU on all the time, using a WakeLock. This will significantly impact the user's battery, causing your app to appear on the Settings app's "battery blame screen". That, in combination with the tying-up-system-RAM "feature", will likely incite some poor ratings for your app.

    Instead, by using AlarmManager:

    • Your IntentService only needs to be running while it is doing its work ("check the server updates"), going away in between these events, so your process can be terminated to free up system RAM for other things that the user is doing

    • By use of the WakefulBroadcastReceiver or WakefulIntentService patterns, you can wake up the device briefly to do this work, then let the device go back to sleep again, thereby minimizing the impact on the battery