I was trying to get the purpose of the IntentService, and when should I use it?
I tried to understand from the API, but not enough details on that one.
Is there any analogy between this and running long-task on a working thread?
Any further explanation and samples on why I would use IntentService would be very welcome.
Thanks,
ray.
Is there any analogy between this and
running long-task on a working thread?
IntentService handles the thread for you.
when should I use it?
Some use cases:
For handling alarms triggered by AlarmManager
For handling other events caught by a manifest-registered BroadcastReceiver
For handling events triggered by an app widget (time-based updates, button clicks, etc.)
Android services are the workhorses of the platform. They allow applications to run long running tasks and give functionality to outside applications. Unfortunately, since they run in the background and are not visually obvious to developers, they can be a source of major headaches. If you have seen an ANR (activity not responding) or have wondered why a service was running when it shouldn't be, a poorly implemented service could be the issue.
The dreaded ANR
Let's take a look at two major errors services cause:
ANRs. These disrupt the user's experience and gives the user an option to force close. This can lead to a user uninstalling your app or the background process being in a disrupted state. The reason for this is that services are launched from your calling thread-- usually this is the UI thread.
Always running services. Although Android provides mechanisms for scheduling and stopping services, not all developers follow the guidelines. In fact, a lot of the examples I've seen don't even mention stopping your service. This can lead to slower overall performance, user confusion, and battery drain.
I imagine the Android developers at Google saw that this was becoming an issue and introduced the IntentService class in Android 1.5. The IntentService class addresses the above issues and abstracts all of the management of threads and service stopping from the developer. It's very easy and powerful way of offloading tasks from the application's main thread.
I would use it whenever the use case is a specific task that will take a long time but has a regular ending. For example, the use cases spelled about above and also such regular tasks such as:
-syncing
-downloading resources
-pulling data from various sources and storing them
I would not recommend using it when the service is long running in nature and doesn't have a definite end. I've seen this done and it is a mistake because the way people end up getting around the fact that IntentService stops itself is to either create locks to keep handleIntent from finishing or if they don't want to block the next requests in line, they'll restart themselves by sending startService again to themselves. This is horrible and for these type of scenarios, you should just use a long running regular Android Service and make sure it's bound to (probably AUTO_CREATE) and handle the work off the main thread.
Related
This is more of a conceptual question than a matter of programming.
I am currently using ReactiveX (RxJava + RxAndroid) to run an interval timer, as the other methods of timers are too inaccurate when it comes down to the milliseconds. From what I understand, ReactiveX requires several threads to operate correctly.
I need the timer to also be running in the background when the user is not on the app itself. But from reading the Services documentation, it seems that background services can only run on the main thread. I was wondering if it is still possible to run the ReactiveX timer in the background despite this limitation. Implementing services would require some major changes to my project, so I thought that I would try asking before doing so.
The project is written in Kotlin, but I doubt that matters. However, any insight on what this code would look like in Kotlin would be appreciated!
Even though the actual work is done in the background, it seems appropriate to use a foreground service, not a background service.
A background service can easily be stopped by the system or even be deferred to maintenance (time) windows.
In order to get a "foreground" for the service it is common to use a notification and bind to it:
https://developer.android.com/guide/components/services#Foreground
As to the other question: The life cycle functions of a Service like onStartCommand() might be called on the main thread but you'd be using RxJava to switch to another thread instantly and return from those functions.
Even after the lifecycle return, the service is considered "running" to the system. They just exist so get things going and should return promptly.
Workmanager is not necessarily a good choice here as it is designed for deferrable tasks. So you cannot be sure when it exactly will be started. Foreground service seems like the way to go here.
my knowledge of services in any operating system, is that they usually run in the background and perform whatever work they have to do.
but the first time I got familiarized with android services, I got confused.
it appears they only run when the application is working, and that for me, makes them no more then sophisticated threads.
do I have this all wrong? how do I make a service that runs when the application doesn't? (so that I can check for updates and create notifications for the user that will then lead him to the application if he chooses to open them).
does push notifications have anything to do with it?
Edit:
thank you guys for your answers so far.
my problem seems to be the fact that the service is only started officialy when the device is booted up. I do call startService when the app starts, but that doesn't seem to help. the service still dies when the app is turned off (unless it was booted)
also I never call stopService
If you are trying to implement a long running task that is performed in a (background) service, you have to start one or more threads within your service. So the service just gives you the opportunity to have an application context without having to have a user interface ;) you can consider it as a kind of container.
This page give you a nice overview about different thread approaches in Android. As you can see a service has not its own thread.
Anyway, in your case it seems that an AlarmManager is probably the better option. Running services for polling information all the time can be quite CPU and battery consuming (see this post for instance). So try to avoid having threads that run all the time.
If you can push information about updates from a server it's just fine. Check out Googles Cloud Messaging in this case.
Michael who commented on my question first was right in his comment about startService()
so it goes like this:
my receiver is only activated on boot, and uses an AlarmManager to
time the service to certain intervals.
what I did was to bind the activities to the service. if the service
was off and I binded it and unbinded it, then by the time the app was
terminated, there was nothing keeping it alive.
by simply making sure that the service was started properly with
startService if it is not already on, I managed to keep the service
alive at all times
also thanks to Trinimon who gave a very nice explanation on what
services are, and the importance of not overloading the CPU with
excessive polling. (which is kind of a trade off situation)
good luck to all :)
It is well known that Android places our application components (Activities, Services) under threat of being killed at any moment. This makes things really complicated if you want to provide a robust, non-leaky solution, while at the same time keeping the code clean and addressing separation of concerns.
Problem:
An activity starts a time-consuming task (in form of a Runnable, AsyncTask or whichever other mechanism). A progress dialog should be displayed. The task will open several connections, but it should have a means of updating a progress bar, and it might need to display a choice dialog half-way to completion. It also should be able to close the dialog and show a Toast when an error occurs, or when it completes.
When an Activity is killed and later a new instance is recreated, I can think of two options:
Try to kill the running task as well, and spawn another task instance when a new substitute activity instance is created. This is not an option for a long running task, as it is unacceptable from a user point of view to start the task and see the progress bar indicator going from 80% back to 0% with no apparent reason. This however is the approach followed in the Shelves example by Romain Guy. Apparently this is the approach recommended in the official Developer Guide.
Keep the task running: So we could have an activity subscribing to (and possibly starting) the task for updates at onResume, and unsubscribing (and possibly pausing) it at onPause.
Following the second option means that we should prevent the task of being collected in case the activity is temporarily destroyed. For instance, we could declare it inside a custom Application class, or even offer it as a service to the rest of the application (using a Singleton? an Android Service?) I'm no fan of this, though, since the task is used only by the activity, so it doesn't make sense to make it available to other classes. Android Services on the other hand also have to deal with life cycle.
Option #2 also involves ensuring the old activity is not leaked. We should not try to update the GUI if no activity is present. The whole think should be thread-safe. Finally the task should not remain in memory after we are sure it is no longer needed. But at the same time, if the initial activity is destroyed, the task keeps running, and a new substitute activity kicks in, the task has to be around to update the GUI immediately and display the task current status (or result in case it completed).
The fact that the task might be running when no activity is shown is another problem to deal with, since we could need user interaction (choice dialog) synchronously at some point. This could be solved if the activity had the ability to immediately pause the task when reaching onPause, but the task could take some time to pause itself or even be unable to do so.
I know similar questions has been asked before, but I'm not asking specifically about how to solve the problem, but about what design would be recommended in order to achieve loose coupling and isolate the activity from the task as much as possible.
In short:
- This is a recurring problem in Android development and someone has probably come up with a clever design before. Is there a design pattern, or a well tested library that simplifies this?
- If you were to implement #2, which class would you choose to for the task (Runnable, Service, etc) and how would it communicate with the activity?
P.S. Please refrain from posting solutions based on the "orientation | keyboardHidden" hack XD. Other than this, any help would be appreciated.
UPDATE:
My first attempt has got a bit messy. The app is a bluetooth printing utility, which involves Detecting BT status (and asking the user to enable it if it were disabled), retrieving paired devices (and asking the user to pick one if there were more than one), then sending the data and finally inform the user about the result. As this task was 80% IO code, 20% GUI-related operations, I had to group the GUI code at the beginning and end of the task, then moving it out of the task back to the activity. I have an IntentService that does the heavy lifting, then reports back to the activity via BroadcastReceiver. This solves most of the problems but there are a few issues with such a design. First, there are all those constant strings used as keys to put and retrieve fields from the input and output Intents, which are introducing semantic coupling. I'd have preferred type-safety in the activity<->service communication. And I yet have to solve how to pass complex custom objects to the service in the Intent, by now I'm stuck with Parcelables and primitive parameters. Finally, both the activity and the service are using the same API (bluetooth), I'd have preferred to have al the BT-related code in a single class. I think I'll throw away this design, and try again with a custom printing queue based on threads, despite it will make harder dealing with killed activities.
why not have your activity start a service to host the long running task? a service is your best-bet for keeping things running long term. you can provide hints to the OS to leave it running. see startForeground() and START_STICKY.
you can communicate back to the activity by broadcasting from the service. have your activity programmatically register a broadcast receiver to listen for those intents. if the activity is paused, unregister your receiver, that way you won't respond when when you aren't in the foreground.
if the OS destroys your service, then it's killing the process, so your task is doomed anyway. the best you can do is restart it. anyway, this won't happen except in the most extreme conditions if you consider the above.
EDIT: summarizing some thoughts captured in the comments ... keeping a long running worker processe and automatically restarting it is almost always the wrong thing to do. mobile devices do not have the power source to make this feasible. the author stated this he has a special condition that negates this concern ... that would only be true if the device is connected to a power source almost always.
the android model is to provide a robust set of intents (notifications) to which your application can listen. these intents wake up your device / application when it's time to do something. your app should handle the notification, and then allow the device to go back to sleep immediately.
if there's no stock intent that maps to your event, you can use Google Cloud Messaging to wake up devices from a server. in other words, let the long-running processes run on the server, and wake up the device when required.
if you can do that, an alternative would be to use AlarmManager to wake up periodically and check some state. even if you did this frequently (e.g., every 5 minutes, which is also a no-no), it'd be much better than keeping the device awake always as is being suggested. also, make use of inexact wakeup intervals (see documentation linked above).
When you learn to develop for Android, you learn that if there's any type of process -that takes more that 5 seconds- running inside the ui thread, the system will show the infamous ANR message. That's when they introduce the evil monster... AsyncTask. At first you see this class as your savior, but then you realize it's the biggest problem in development... Handling rotation or ui events becomes so problematic, it's even painful.
What do you guys think about it... are AsyncTasks worth the trouble? Any other method that makes it less of a problem to perform long running tasks regardless of screen rotation?
I guess you'll probably say, hey why don't you just make it a Service... Yeah that's a solution, but then let's go to my real question. Why don't we just use services and stop using AsyncTasks completely... Are they useful at all?
While developing it is always good to choose the suitable component for the execution. You need to clear your requirement and according to it you can choose between a Service or an AsyncTask.
A service is an Android component that lives independently from any other components. Activities may come and go, but services can stick around, if you wish. They serve a number of roles, from managing state that multiple activities rely upon to serving as cron jobs to handling longer app widget updates.
AsyncTask is a class that arranges to do some work off the main application thread. From the implementer and user of the AsyncTask, how it performs that bit of magic is not generally important. In reality, it uses a thread pool and work queue. AsyncTask uses a Handler to help arrange for select bits of work to be done on the main application thread (e.g., notifying the user of progress updates).
For more clarification see the difference between them.
AsyncTasks and Services are not peers. Either might invoke the other, their purposes are different. I have just a few things to add to Lucifer's answer.
A key thing to remember is that if your process is in the background, hosts a Service, and is killed, that Service will be reincarnated at some point. This is not the case for an AsyncTask that may be running in a process when it is killed. This means that work being done in a Service is guaranteed to make forward progress in the future (although its not guaranteed when). If you have work that must be done, better to do it in a Service.
Calls to Service.onStart and Service.onStartCommand happen on the process' main thread. If you block this for a long time, you'll get the same "app not responding" dialog. As a result, an AsyncTask can be a great thing to use inside a Service to do the real work.
I tend to use AsyncTasks initiated from an Activity for things related to the UI. These are often things that aren't required work and whose work can be easily redone in the future. For example, this might be reading a bunch of images off disk or make a calling to a web service to see if the user has any notifications. This work can be done again, and if the UI is destroyed because the process is killed the work probably needs to be done again anyway.
If on the other hand you want to say upload a group of photos to the web as soon as possible, I'd farm this out to a Service which will use one or more AsyncTasks to do it. This is work I want to get done and want to be resumed if it gets interrupted. If you're going to use a Service, consider using an IntentService so that your Service stops when its work is done.
My application is essentially a service that is started on boot (by a boot-completed receiver), and should periodically gather data, send it over the network, and go to sleep (probably using AlarmManager). It has no activities - no UI whatsoever.
Is there any reason to spawn an additional thread to perform the application logic?
if not, where should I perform the logic? in the OnStart method?
Is there any reason to spawn an additional thread to perform the application logic?
Absolutely. Your service will be killed off if it fails to respond within 5-10 seconds. Nothing can tie up the main application thread for that length of time.
I recommend an IntentService for use with AlarmManager. In particular, if you want the device to stay awake while you are doing whatever it is you are doing, you might consider my WakefulIntentService.
Also, regarding "no UI whatsoever", if you plan on distributing this app via the Android Market, please bear in mind that users seem to dislike applications with no UI. They install it, get confused when there is no icon in the launcher, and give you a one-star rating. Even if you do not need a UI for actual operation, you might consider at least having some activity in the launcher, that shows documentation, perhaps a log of work being done, allows adjustment to the frequency of your work, etc.