-
Started
-
A service is "started" when an application component (such as an activity) starts it bycalling
startService()
. Once started, a servicecan run in the background indefinitely, even if the component that started it is destroyed. Usually,a started service performs a single operation and does not return a result to the caller.For example, it might download or upload a file over the network. When the operation is done, theservice should stop itself
-
Bound
-
A service is "bound" when an application component binds to it by calling
bindService()
. A bound service offers a client-serverinterface that allows components to interact with the service, send requests, get results, and evendo so across processes with interprocess communication (IPC). A bound service runs only as long asanother application component is bound to it. Multiple components can bind to the service at once,but when all of them unbind, the service is destroyed.
Caution: A services runs in the same process as the applicationin which it is declared and in the main thread of that application, by default. So, if your serviceperforms intensive or blocking operations while the user interacts with an activity from the sameapplication, the service will slow down activity performance. To avoid impacting applicationperformance, you should start a new thread inside the service.
Traditionally, there are two classes you can extend to create a started service:
- This is the base class for all services. When you extend this class, it's important thatyou create a new thread in which to do all the service's work, because the service uses yourapplication's main thread, by default, which could slow the performance of any activity yourapplication is running.
-
This is a subclass of
Service
that uses a worker thread to handle allstart requests, one at a time. This is the best option if you don't require that your servicehandle multiple requests simultaneously. All you need to do is implementonHandleIntent()
, which receives the intent for eachstart request so you can do the background work.
Service
IntentService
Extending the IntentService class
Because most started services don't need to handle multiple requests simultaneously(which can actually be a dangerous multi-threading scenario), it's probably best if youimplement your service using the IntentService
class.
The IntentService
does the following:
- Creates a default worker thread that executes all intents delivered to
onStartCommand()
separate from your application's mainthread. - Creates a work queue that passes one intent at a time to your
onHandleIntent()
implementation, so you never have toworry about multi-threading. - Stops the service after all start requests have been handled, so you never have to call
stopSelf()
. - Provides default implementation of
onBind()
thatreturns null. - Provides a default implementation of
onStartCommand()
that sends the intent to the work queue and then to youronHandleIntent()
implementation.
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
public class HelloService extends Service { private Looper mServiceLooper; private ServiceHandler mServiceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } } } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; mServiceHandler.sendMessage(msg); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }