Service vs Runnable vs AsyncTask - android

I'm developing a countdown timer app for Android. The app can show the remaining time. It has to be working even the phone is locked or the main activity is destroyed. I was wondering which of the following should I use and, more importantly, why should I use it (and why not the others).
Service
Runnable : A static reference to a Runnable object. The reference is declared in an Activity class.
AsyncTask

In my opinion, I would use a service if your application needs to be able to notify user in background, so if your application has been put in background by the user, you can still notify the user when you timer is ready, and then can use location based event time, etc.

A Service would be best in this situation, it would, as you require, carry on running even when the main activity is destroyed and would be less prone to being killed by the Android OS.
Both AsyncTask and runnable would rely on your application still being alive, whereas a Service runs independently and you would bind the Activity to it when it is opened or re-started to show information passed from the service, or the service could on it's own, display notifications and so on.

You can use Handler, Check here
http://developer.android.com/resources/articles/timed-ui-updates.html

Related

Why would anyone want to bind service (without creating it), instead of using a Thread?

Until today, I used services by starting them, using startService(), because I needed to do work also when all the activities was destroyed.
Now, I have a task that needs to be done in the background as long as my activity is alive.
Is there a reason for me to bind the activity to a service instead of doing the work in a separate thread?
It leads me to the question in the title:
Why would anyone want to bind service (without creating it before), instead of using a Thread?
Services and Thread have two different goals. As you mentioned, Service can live longer after the activity was destroyed. Depending on the Service you subclassed it runs or not on the UI Thread. They have their own life cycle and are a construct of the Android SDK. Threads are unit of executions whose flow is parallel to the ui thread. It allows you to execute long term tasks leaving the ui responsive. The Thread lives as long as its run's method. You should make sure that its execution is completed before your Activity or Fragment calls its onDestroy method.
Why would anyone want to bind service instead of using a Thread?
The answer is it depends. If you need to run your task also when you Activity is destroyed, then a Service is the natural choice. Otherwise you can use a simple thread. Think, for instance, about downloading a huge file from the net. You want to run this task also when the activity is not at screen but, at the same time, you want to show to the user the current progress (in percentage maybe) of the download. If you are using a Service to run this task, this one holds also those information. To update your UI, which is part of the Activity, you could either Broadcast those information, or retrive the Service object, the one you get when your service is bound, to retrieve this information (providing a delegate). Since you get an instance of your service, you can use it to send different kind of commands (e.g. stop the download).
Is there a reason for me to bind the activity to a service
instead of doing the work in a separate thread?
If your thread lives in a non static member variable of the activity and the activity is recreated after screen rotation your thread is lost or has to be recreated.
With a service you can reconnect to the service after rotation.
Instead of using a naked thread or a service i prefer to use a LoaderManager with an AsyncTask to do the background task while the activity is visible. The LoaderManager is also capable of reconnecting to the running AsyncTask
I avoid using static member variable for thread/AsyncTask because of memory leaking issues.

want to make the service independently run

So basically what i am trying to do is i want a service that runs in background and updates the LatLong to the server. This operation needs to happen all the time even if the application is running or not.
Now when the application is launched i want the service to calculate the distance between the latlong and update the UI in addition to the work that it was already doing i.e. updating the latlong to the server. i want the service to do the additional work for multiple activities. lets say i launch the application and i am on Activity A, onclick of a button on Activity A the service starts updating the UI and when we click gain it stops updating. Now i am on Activity B and on click i want the service to do some work in addition to the updation of LatLong and update the UI.
What would be the best approach to achieve this.??
EDIT
The problem i am facing is not getting the service update the UI but making the activity communicate with the service when it has already started.
i can pass on some data when i am starting the service but how to communicate with the service when it has already started. How to tell the service that see you are already running and doing some operations now you have to perform some more operation on top of the previous operation.
I can make some static method in the service and call them when i need to perform the extra operation but i dont wanna do that.. i want to better approach.
Here is the basically services runs on the same main thread process as ui. When you want make it run continuously you have run it in your tread. In this way you avoid service being get stopped as application go in background or killed. (Please take look at Service.START_STICKY flag, this is what you need as i guess).
And more coming your second problem of activity getting updated with service information or data that is being collected for this you need look at " How Bind the service". (In activity check for service connection and Binding to a activity, Unbindibg is also there have look at it also). Activity has all the call backs for it you need to implement binder.
EDIT
Service to update ui has to have send and receive intent mechanism. You can broadcast and intent from the services check your activity is running or not. If running broadcast intent and have receiver in activity to listen it.
You can do it by interface mechanism too

Please, explain some Android Service Concepts

I'm just approaching Android Services, but i have many doubts. Here there are some questions.
Before starting, notice i have read those pages
Android Services (official)
Bounded Services (official)
plus sone Inner classes theory in my language. Please be patient, i'm still a bit confused.
1) First of all, a Services differentiates itself from an AsyncTask mainly because it continues to run also if the app is paused (i.e. the user is watching another app); AsyncTask is stopped in that cases. Is it ok or am i wrong?
2) A Service runs in the same thread of the activity that started it through startService().
To not affect the Activity's performances, i have to create a separate thread for that Service, for example implementing the Runnable interface. Another method is making a service that extends IntentService, which automatically provides a new thread for the service: a new thread is created on any onHandleIntent() call.
Now, let's look at my concrete problem. I need to create a Service that will be used by many Activities: his task will be to connect to the server DB every 60 seconds and check for news. If a news is found, notify there's a new news (if we are on MainActivity) or show the new news's title (if we are in the news reader). How should i code it?
I have made a MainActivity that instantiate a NewsService and immediately calls startService(). On the other side, i have the NewsService extends IntentService, that (creates a new thread when onHandleIntent is called?) and looks for new news. Is it a bad idea to use a IntentService? I realized it will be very ugly to start the service calling startService() indefinitely.
At the start of this exercize i tought it was a good solution because it automatically creates a new thread and makes Service implementation simple. But now i have some doubts (i can't know if there's a news! How can MainActivity know it? And how to get the title)
This should be done with a normal extends Thread class, that makes an infinite cicle in it's run() method, checking for news every 60 seconds and, if there's a new one, reads the title from remote DB AND update activities buttons/views. Then if the App will be closed by user, the Service will be closed too.
But the problem is that if i istantiate such class it's work will be stopped when the MainActivity is paused or stopped, and other Activities (the NewsReader in this case) cannot get any update because the new thread isn't getting news at the moment. So i need a Service.
I hope it's clear. How should i implement a solution in the right way?
Please highlight everything wrong in my text, i really need to learn :D
You seem to have understood everything correctly.
As to your specific problem, I'd recommend the following:
Use AlarmManager to schedule your service. Don't let the Service run when it does not have to.
Use a Broadcast Intent for new news. All Activities will have to have an inner BroadcastReceiver that listens for the Broadcast intent of the service and reacts accordingly.
Services are a good approach for what you want, they are pretty good to do processes that consume few resources like keeping a daemon in background, they are also good to show notifications without an activity and keep running even if you exit the activity.
When you need to do more heavy operations in your service you can still use an AsyncTask, launch it, execute your operation in another thread and automatically receive the result in your main thread.
If you want to keep the service always running you can use START_STICKY in your Service
#Override
public int onStartCommand(final Intent intent, final int flags,
final int startId) {
// Ensure the service will restart if it dies
return START_STICKY;
}
And you can launch the service doing:
final Intent service = new Intent();
service.setComponent(new ComponentName(YourService.PACKAGE_NAME,
YourService.SERVICE_FULL_NAME));
// Start the service
context.startService(service);
1) First of all, a Services differentiates itself from an AsyncTask
mainly because it continues to run also if the app is paused (i.e. the
user is watching another app); AsyncTask is stopped in that cases. Is
it ok or am i wrong?
This is not correct. AsyncTask is a mechanism for offloading background processing into a separate thread and provides a mechanism for informing the user of progress, error and completion of that background processing. AsyncTask does not stop working if the app is paused. It continues to perform its processing in the background. In general, there is tight coupling between an AsyncTask and the Activity that started it.
A Service, on the other hand, is (generally) completely decoupled from the Activity that started it. A Service has its own lifecycle which is independent of the other activities in the app. Also, services have no UI, so they are not linked to the visual elements of the application and they provide no (direct) mechanisms for visual feedback related to progress, error or completion. This needs to programmed separately.
2) A Service runs in the same thread of the
activity that started it through startService(). To not affect the
Activity's performances, i have to create a separate thread for that
Service, for example implementing the Runnable interface. Another
method is making a service that extends IntentService, which
automatically provides a new thread for the service: a new thread is
created on any onHandleIntent() call.
This isn't correct either. A Service doesn't run on any specific thread. The lifecycle methods of a Service (onCreate(), onStartCommand(), etc.) run on the main (UI) thread, which may or may not be the same thread that called startService(). However, a Service can (and usually does) start other background threads, as many as it needs to, to perform the necessary work.
IntentService is a specific kind of Service which manages one or more worker threads that it uses to perform background processing. You send a "command" to an IntentService and the IntentService then puts your command in a queue. At some point (different implementations in different Android versions behave differently), your "command" is dequeued and processed in a background thread. IntentService stops itself after all the "commands" have been processed. IntentService is often not the best choice for a Service due to the way it behaves.
IntentService is definitely not what you want in your case. You should probably use AlarmManager and set an alarm that starts your Service every minute. When your Service starts, it should create a background thread that contacts your server and checks for news. If there is no news it can just go away. If there is new news, it can either start your Activity to inform the user, or it can send a broadcast Intent which your Activity will see (if it is running),or it could create a Notification which the user can then open whenever he wants to. You need to figure out how you want to determine when the app should stop checking the server. Maybe the user should tell you that he isn't interested anymore, or maybe the Service can recognize that the app isn't running anymore (or hasn't been looked at in more than X hours or whatever). There are lots of ways to do this and it depends on your requirements.

How do I use the Service feature in Android

I am new to android development and having trouble understanding how I should use service's and more specifically which kind. I am developing an simple system that only will do to things. One of those to is to continuously ask a server simple telnet questions. The answer to these questions should be prompted on the screen.
So to simplify my question. What kind of service should I prefer? bound, intent service etc?
I presume it has to run a own thread since it is suppose to do network comm, so how should I do that.
Finally and most importantly, how do I supply/give the MainActivity the information the service has gathered and post it on the screen?
What kind of service should I prefere? bound, intentservice etc?
A bound service runs only as long as another application component is bound to it. With other words, if an activity bounds to that service, and later that activity gets finished, the service also gets destroyed.
So, first decide the behaviour of the service you want to have. Do you want it to be destroyed when the activity bound to it gets destroyed? If yes, then perhaps a bound service is the right thing to do, if not then use a started service instead which can run in the background indefinitely, even if the component that started it is destroyed.
I presume it has to run a own thread since it is suppose to do network
comm, so how should I do that.
Yes, you are right. You can use the Service class and create a thread inside it that will do the heavy work, or, you could simplify things by using an IntentService which provides its own worker thread.
Finally and most importantly, how do I supply/give the MainActivity
the information the service has gathered?
If you decide to go with a bound Service, then you'll be able to communicate with the service through a so called binder object. On the other hand if you go with IntentService then you could use a ResultReceiver, or a BroadcastReceiver to send the result back.
Suggested readings:
http://developer.android.com/guide/components/services.html
http://developer.android.com/guide/components/bound-services.html
Here is a quick summary on services in Android, hopefully this will help in deciding what approach to go. Reading Android Services is highly recommended
Android Service
"A Service is an application component that can perform long-running
operations in the background and does not provide a user interface"
runs on the main (UI) application thread.
it is given preference over activities in termination when resources
are low
it is not intended to interact directly with an activity/fragment (an activity may be destroyed at any time) no simple callback ability due to above... however there are some ways to address this using Intents, Handlers and Messages
an activity can be bound to a service which
basically gives an instance of the service to call methods, the methods will run on the main thread, a suggested way to use a separate thread, is to use Executors

Android Worker Threads and the Application life cycle

I have a application in which I have a UART (Serial Comms) to service and several other "tasks" that require separate worker threads to keep the UI responsive. My problem is in understanding when/where I should create these threads and when they get terminated. Currently, I am creating them in the OnCreate() of the main UI Activity. But, this is causing havok, as I recently needed to "jump" from one Activity back to the Main activity. The recommendation was to use an Intent and StartActivity() with the appropriate flags to "clear to top". But, this of course causes a whole new set of instances for my threads, and everything unravels. Should I be using a Service, tied to my UI somehow? I have subclassed my Main Application, so I have the OnCreate() of my Application. I'm leaning towards that, but can't seem to grasp the life cycle of the Application versus the Activities.
Use a service. You have an ongoing task that isn't inherently attached to one particular activity.
You can start a long running task with startService and the service will not be killed until it's finished. Meanwhile, Context#bindService will keep the service alive as long as anything is bound to it.
General rule of android concurrent programming
If you need to do something off the UI thread and return a result, use an AsyncTask created when you want to use it
If you have a 1 off requirement to do some work (say post a webservice request), use an AsyncTask
If you repeatedly want to do something inside a single activity but you don't need to run after the activity is destroyed or send data to another service, use a thread
If you need to talk to multiple activities, use a service.
If you need to run before/after your launching activity ends, use a service

Categories

Resources