diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java index 7c2d3a091d40c..57a26959bc8ca 100644 --- a/core/java/android/app/IntentService.java +++ b/core/java/android/app/IntentService.java @@ -113,6 +113,12 @@ public abstract class IntentService extends Service { mServiceHandler.sendMessage(msg); } + /** + * You should not override this method for your IntentService. Instead, + * override {@link #onHandleIntent}, which the system calls when the IntentService + * receives a start request. + * @see android.app.Service#onStartCommand + */ @Override public int onStartCommand(Intent intent, int flags, int startId) { onStart(intent, startId); @@ -124,6 +130,11 @@ public abstract class IntentService extends Service { mServiceLooper.quit(); } + /** + * Unless you provide binding for your service, you don't need to implement this + * method, because the default implementation returns null. + * @see android.app.Service#onBind + */ @Override public IBinder onBind(Intent intent) { return null; @@ -135,6 +146,8 @@ public abstract class IntentService extends Service { * worker thread that runs independently from other application logic. * So, if this code takes a long time, it will hold up other requests to * the same IntentService, but it will not hold up anything else. + * When all requests have been handled, the IntentService stops itself, + * so you should not call {@link #stopSelf}. * * @param intent The value passed to {@link * android.content.Context#startService(Intent)}. diff --git a/docs/html/guide/topics/advanced/aidl.jd b/docs/html/guide/topics/advanced/aidl.jd new file mode 100644 index 0000000000000..fef46eca464fa --- /dev/null +++ b/docs/html/guide/topics/advanced/aidl.jd @@ -0,0 +1,387 @@ +page.title=Android Interface Definition Language (AIDL) +@jd:body + + + +
AIDL (Android Interface Definition Language) is similar to other IDLs you might have +worked with. It allows you to define the programming interface that both +the client and service agree upon in order to communicate with each other and allows for +interprocess communication (IPC). On Android, one process can not normally access the +memory of another process. So to talk, they need to decompose their objects into primitives that the +operating system can understand, and "marshall" the object across that boundary for you. The code to +do that marshalling is tedious to write, so Android handles it for you with AIDL.
+ +Note: Using AIDL is necessary only if you allow clients from +different applications to access your service for IPC and want to handle multithreading in your +service. If you do not need to perform IPC across +different applications, you should create your interface implementing a +Binder or, if you want to perform IPC, but do not need to handle multithreading, then you +should implement your interface using a Messenger.
+ +Before you begin designing your AIDL interface, be aware that calls on to an AIDL interface are +direct function calls. You can not generally make assumptions about the thread in which the call +will happen. What happens is different depending on whether the call is from a thread in the +local process, or coming from a remote process. Specifically:
+ +You must define your AIDL interface in an {@code .aidl} file using the Java +programming language syntax, then save it in the source code (in the {@code src/} directory) of both +the application hosting the service and any other application that will bind to the service.
+ +When you build the projects containing the {@code .aidl} file, the Android SDK tools generate an +{@link android.os.IBinder} class based on your AIDL interface (and saves the file in the {@code +gen/} directory). This class defines the APIs you can call to perform RPC as an interface—you +must implement the interface in your service.
+ +To create a bounded service using AIDL, follow these steps:
+This file defines the programming interface with method signatures.
+The Android SDK tools generate an interface in the Java programming language, based on your +{@code .aidl} file. This interface has an inner abstract class named {@code Stub} that extends +{@link android.os.Binder} and implements methods from your AIDL interface. You must extend the +{@code Stub} class and implement the methods.
+Implement a {@link android.app.Service Service} and override {@link +android.app.Service#onBind onBind()} to return your implementation of the {@code Stub} +class.
+Caution: Any changes that you make to your AIDL interface after +your first release must remain backward compatible in order to avoid breaking other applications +that use your service. That is, because your {@code .aidl} file must be copied to other applications +in order for them to access your service's interface, you must maintain support for the original +interface.
+ + +AIDL uses a simple syntax that lets you declare an interface with one or more methods that can +take parameters and return values. The parameters and return values can be of any type, even other +AIDL-generated interfaces.
+ +The syntax for the {@code .aidl} file uses the Java programming language. The file defines a +single interface and requires only the interface declaration and method signatures.
+ +By default, AIDL supports the following data types:
+ +All elements in the {@link java.util.List} must be one of the supported data types in this
+list or one of the other AIDL-generated interfaces or parcelables you've declared. A {@link
+java.util.List} may optionally be used as a "generic" class (e.g. List<String>).
+The actual concrete class that the other side will receive will always be an {@link
+java.util.ArrayList}, although the method will be generated to use the {@link
+java.util.List} interface.
All elements in the {@link java.util.Map} must be one of the supported data types in this +list or one of the other AIDL-generated interfaces or parcelables you've declared. Generic maps, +(such as those of the form +{@code Map<String,Integer>} are not supported. The actual concrete class that the other side +will receive will always be a {@link java.util.HashMap}, although the method will be generated to +use the {@link java.util.Map} interface.
+You must include an {@code import} statement for each additional type not listed above, even if +they are defined in the same package as your interface.
+ +When defining methods for your service interface, be aware that:
+in, out, or inout (see the example below).
+ Primitives are in by default, and cannot be otherwise.
Caution: You should limit the direction to what is truly +needed, because marshalling parameters is expensive.
Here is an example {@code .aidl} file:
+ +
+// IRemoteService.aidl
+package com.example.android;
+
+// Declare any non-default types here with import statements
+
+/** Example service interface */
+interface IRemoteService {
+ /** Request the process ID of this service, to do evil things with it. */
+ int getPid();
+
+ /** Demonstrates some basic types that you can use as parameters
+ * and return values in AIDL.
+ */
+ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
+ double aDouble, String aString);
+}
+
+
+Simply save your {@code .aidl} file in your project's {@code src/} directory and when you +build your application, the SDK tools will generate the binder class file in your project's +{@code gen/} directory. The generated file name matches the {@code .aidl} file name, but with a +{@code .java} extension (for example, {@code IRemoteService.aidl} results in {@code +IRemoteService.java}).
+ +If you use Eclipse, the incremental build generates the binder class almost immediately. If you
+do not use Eclipse, then the Ant tool generates the binder class next time you build your
+application—you should build your project with ant debug (or ant
+release) as soon as you're finished writing the {@code .aidl} file, so that your code can
+link against the generated class.
When you build your application, the Android SDK tools generate a {@code .java} interface file +named after your {@code .aidl} file. The generated interface includes a subclass named {@code Stub} +that is an abstract implementation of its parent interface (for example, {@code +YourInterface.Stub}) and declares all the methods from the {@code .aidl} file.
+ +Note: {@code Stub} also +defines a few helper methods, most notably {@code asInterface()}, which takes an {@link +android.os.IBinder} (usually the one passed to a client's {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method) and +returns an instance of the stub interface. See the section Calling an IPC +Method for more details on how to make this cast.
+ +To implement the interface generated from the {@code .aidl}, extend the generated {@link +android.os.Binder} interface (for example, {@code YourInterface.Stub}) and implement the methods +inherited from the {@code .aidl} file.
+ +Here is an example implementation of an interface called {@code IRemoteService} (defined by the +{@code IRemoteService.aidl} example, above) using an anonymous instance:
+ +
+private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+ public int getPid(){
+ return Process.myPid();
+ }
+ public void basicTypes(int anInt, long aLong, boolean aBoolean,
+ float aFloat, double aDouble, String aString) {
+ // Does nothing
+ }
+};
+
+
+Now the {@code mBinder} is an instance of the {@code Stub} class (a {@link android.os.Binder}), +which defines the RPC interface for the service. In the next step, this instance is exposed to +clients so they can interact with the service.
+ +There are a few rules you should be aware of when implementing your AIDL interface:
+Once you've implemented the interface for your service, you need to expose it to +clients so they can bind to it. To expose the interface +for your service, extend {@link android.app.Service Service} and implement {@link +android.app.Service#onBind onBind()} to return an instance of your class that implements +the generated {@code Stub} (as discussed in the previous section). Here's an example +service that exposes the {@code IRemoteService} example interface to clients.
+ +
+public class RemoteService extends Service {
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ // Return the interface
+ return mBinder;
+ }
+
+ private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+ public int getPid(){
+ return Process.myPid();
+ }
+ public void basicTypes(int anInt, long aLong, boolean aBoolean,
+ float aFloat, double aDouble, String aString) {
+ // Does nothing
+ }
+ };
+}
+
+
+Now, when a client (such as an activity) calls {@link android.content.Context#bindService +bindService()} to connect to this service, the client's {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback receives the +{@code mBinder} instance returned by the service's {@link android.app.Service#onBind onBind()} +method.
+ +The client must also have access to the interface class, so if the client and service are in +separate applications, then the client's application must have a copy of the {@code .aidl} file +in its {@code src/} directory (which generates the {@code android.os.Binder} +interface—providing the client access to the AIDL methods).
+ +When the client receives the {@link android.os.IBinder} in the {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback, it must call
+YourServiceInterface.Stub.asInterface(service) to cast the returned
+parameter to YourServiceInterface type. For example:
+IRemoteService mIRemoteService;
+private ServiceConnection mConnection = new ServiceConnection() {
+ // Called when the connection with the service is established
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ // Following the example above for an AIDL interface,
+ // this gets an instance of the IRemoteInterface, which we can use to call on the service
+ mIRemoteService = IRemoteService.Stub.asInterface(service);
+ }
+
+ // Called when the connection with the service disconnects unexpectedly
+ public void onServiceDisconnected(ComponentName className) {
+ Log.e(TAG, "onServiceDisconnected");
+ }
+};
+
+
+For more sample code, see the {@code +RemoteService.java} class in ApiDemos.
+ + + + + + + + +If you have a class that you would like to send from one process to another through +an IPC interface, you can do that. However, you must ensure that the code for your class is +available to the other side of the IPC and the class must support the {@link +android.os.Parcelable} interface, in order for the objects to be decomposed into primitives and +marshalled across processes by the Android system.
+ +There are five parts to making a class support the {@link android.os.Parcelable} protocol: +
CREATOR to your class which is an object implementing
+the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.If you are using a custom build process, do not add the {@code .aidl} file to your +build. Similar to a header file in the C language, this {@code .aidl} file isn't compiled.
AIDL will use these methods and fields in the code it generates to marshall and unmarshall +your objects.
+ +For example, here is a {@code Rect.aidl} file to create a {@code Rect} class that's +parcelable:
+ ++package android.graphics; + +// Declare Rect so AIDL can find it and knows that it implements +// the parcelable protocol. +parcelable Rect; ++ +
And here is an example of how the {@link android.graphics.Rect} class implements the +{@link android.os.Parcelable} protocol.
+ +
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public final class Rect implements Parcelable {
+ public int left;
+ public int top;
+ public int right;
+ public int bottom;
+
+ public static final Parcelable.Creator<Rect> CREATOR = new
+Parcelable.Creator<Rect>() {
+ public Rect createFromParcel(Parcel in) {
+ return new Rect(in);
+ }
+
+ public Rect[] newArray(int size) {
+ return new Rect[size];
+ }
+ };
+
+ public Rect() {
+ }
+
+ private Rect(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeInt(left);
+ out.writeInt(top);
+ out.writeInt(right);
+ out.writeInt(bottom);
+ }
+
+ public void readFromParcel(Parcel in) {
+ left = in.readInt();
+ top = in.readInt();
+ right = in.readInt();
+ bottom = in.readInt();
+ }
+}
+
+
+The marshalling in the {@code Rect} class is pretty simple. Take a look at the other +methods on {@link android.os.Parcel} to see the other kinds of values you can write +to a Parcel.
+ +Warning: Don't forget the security implications of receiving +data from other processes. In this case, the {@code Rect} will read four numbers from the {@link +android.os.Parcel}, but it is up to you to ensure that these are within the acceptable range of +values for whatever the caller is trying to do. See Security and Permissions for more +information about how to keep your application secure from malware.
+ diff --git a/docs/html/guide/topics/fundamentals/bound-services.jd b/docs/html/guide/topics/fundamentals/bound-services.jd new file mode 100644 index 0000000000000..e5d626c0799cc --- /dev/null +++ b/docs/html/guide/topics/fundamentals/bound-services.jd @@ -0,0 +1,675 @@ +page.title=Bound Services +parent.title=Services +parent.link=services.html +@jd:body + + +A bound service is the server in a client-server interface. A bound service allows components +(such as activities) to bind to the service, send requests, receive responses, and even perform +interprocess communication (IPC). A bound service typically lives only while it serves another +application component and does not run in the background indefinitely.
+ +This document shows you how to create a bound service, including how to bind +to the service from other application components. However, you should also refer to the Services document for additional +information about services in general, such as how to deliver notifications from a service, set +the service to run in the foreground, and more.
+ + +A bound service is an implementation of the {@link android.app.Service} class that allows +other applications to bind to it and interact with it. To provide binding for a +service, you must implement the {@link android.app.Service#onBind onBind()} callback method. This +method returns an {@link android.os.IBinder} object that defines the programming interface that +clients can use to interact with the service.
+ +As discussed in the Services +document, you can create a service that is both started and bound. That is, the service can be +started by calling {@link android.content.Context#startService startService()}, which allows the +service to run indefinitely, and also allow a client to bind to the service by calling {@link +android.content.Context#bindService bindService()}. +
If you do allow your service to be started and bound, then when the service has been +started, the system does not destroy the service when all clients unbind. Instead, you must +explicitly stop the service, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}.
+ +Although you should usually implement either {@link android.app.Service#onBind onBind()} +or {@link android.app.Service#onStartCommand onStartCommand()}, it's sometimes necessary to +implement both. For example, a music player might find it useful to allow its service to run +indefinitely and also provide binding. This way, an activity can start the service to play some +music and the music continues to play even if the user leaves the application. Then, when the user +returns to the application, the activity can bind to the service to regain control of playback.
+ +Be sure to read the section about Managing the Lifecycle of a Bound +Service, for more information about the service lifecycle when adding binding to a +started service.
+A client can bind to the service by calling {@link android.content.Context#bindService +bindService()}. When it does, it must provide an implementation of {@link +android.content.ServiceConnection}, which monitors the connection with the service. The {@link +android.content.Context#bindService bindService()} method returns immediately without a value, but +when the Android system creates the connection between the +client and service, it calls {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} on the {@link +android.content.ServiceConnection}, to deliver the {@link android.os.IBinder} that +the client can use to communicate with the service.
+ +Multiple clients can connect to the service at once. However, the system calls your service's +{@link android.app.Service#onBind onBind()} method to retrieve the {@link android.os.IBinder} only +when the first client binds. The system then delivers the same {@link android.os.IBinder} to any +additional clients that bind, without calling {@link android.app.Service#onBind onBind()} again.
+ +When the last client unbinds from the service, the system destroys the service (unless the +service was also started by {@link android.content.Context#startService startService()}).
+ +When you implement your bound service, the most important part is defining the interface +that your {@link android.app.Service#onBind onBind()} callback method returns. There are a few +different ways you can define your service's {@link android.os.IBinder} interface and the following +section discusses each technique.
+ + + +When creating a service that provides binding, you must provide an {@link android.os.IBinder} +that provides the programming interface that clients can use to interact with the service. There +are three ways you can define the interface:
+ +This is the preferred technique when your service is merely a background worker for your own +application. The only reason you would not create your interface this way is because +your service is used by other applications or across separate processes.
This is the simplest way to perform interprocess communication (IPC), because the {@link +android.os.Messenger} queues all requests into a single thread so that you don't have to design +your service to be thread-safe.
+To use AIDL directly, you must +create an {@code .aidl} file that defines the programming interface. The Android SDK tools use +this file to generate an abstract class that implements the interface and handles IPC, which you +can then extend within your service.
+Note: Most applications should not use AIDL to +create a bound service, because it may require multithreading capabilities and +can result in a more complicated implementation. As such, AIDL is not suitable for most applications +and this document does not discuss how to use it for your service. If you're certain that you need +to use AIDL directly, see the AIDL +document.
+ + + + +If your service is used only by the local application and does not need to work across processes, +then you can implement your own {@link android.os.Binder} class that provides your client direct +access to public methods in the service.
+ +Note: This works only if the client and service are in the same +application and process, which is most common. For example, this would work well for a music +application that needs to bind an activity to its own service that's playing music in the +background.
+ +Here's how to set it up:
+Note: The reason the service and client must be in the same +application is so the client can cast the returned object and properly call its APIs. The service +and client must also be in the same process, because this technique does not perform any +marshalling across processes.
+ +For example, here's a service that provides clients access to methods in the service through +a {@link android.os.Binder} implementation:
+ +
+public class LocalService extends Service {
+ // Binder given to clients
+ private final IBinder mBinder = new LocalBinder();
+ // Random number generator
+ private final Random mGenerator = new Random();
+
+ /**
+ * Class used for the client Binder. Because we know this service always
+ * runs in the same process as its clients, we don't need to deal with IPC.
+ */
+ public class LocalBinder extends Binder {
+ LocalService getService() {
+ // Return this instance of LocalService so clients can call public methods
+ return LocalService.this;
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ /** method for clients */
+ public int getRandomNumber() {
+ return mGenerator.nextInt(100);
+ }
+}
+
+
+The {@code LocalBinder} provides the {@code getService()} method for clients to retrieve the +current instance of {@code LocalService}. This allows clients to call public methods in the +service. For example, clients can call {@code getRandomNumber()} from the service.
+ +Here's an activity that binds to {@code LocalService} and calls {@code getRandomNumber()} +when a button is clicked:
+ +
+public class BindingActivity extends Activity {
+ LocalService mService;
+ boolean mBound = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ // Bind to LocalService
+ Intent intent = new Intent(this, LocalService.class);
+ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ // Unbind from the service
+ if (mBound) {
+ unbindService(mConnection);
+ mBound = false;
+ }
+ }
+
+ /** Called when a button is clicked (the button in the layout file attaches to
+ * this method with the android:onClick attribute) */
+ public void onButtonClick(View v) {
+ if (mBound) {
+ // Call a method from the LocalService.
+ // However, if this call were something that might hang, then this request should
+ // occur in a separate thread to avoid slowing down the activity performance.
+ int num = mService.getRandomNumber();
+ Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ /** Defines callbacks for service binding, passed to bindService() */
+ private ServiceConnection mConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName className,
+ IBinder service) {
+ // We've bound to LocalService, cast the IBinder and get LocalService instance
+ LocalBinder binder = (LocalBinder) service;
+ mService = binder.getService();
+ mBound = true;
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName arg0) {
+ mBound = false;
+ }
+ };
+}
+
+
+The above sample shows how the client binds to the service using an implementation of +{@link android.content.ServiceConnection} and the {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback. The next +section provides more information about this process of binding to the service.
+ +Note: The example above doesn't explicitly unbind from the service, +but all clients should unbind at an appropriate time (such as when the activity pauses).
+ +For more sample code, see the {@code +LocalService.java} class and the {@code +LocalServiceActivities.java} class in ApiDemos.
+ + + + + +When you need to perform IPC, using a {@link android.os.Messenger} for your interface is +simpler than implementing it with AIDL, because {@link android.os.Messenger} queues +all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the +service, which must then handle multi-threading.
+For most applications, the service doesn't need to perform multi-threading, so using a {@link +android.os.Messenger} allows the service to handle one call at a time. If it's important +that your service be multi-threaded, then you should use AIDL to define your interface.
+If you need your service to communicate with remote processes, then you can use a +{@link android.os.Messenger} to provide the interface for your service. This technique allows +you to perform interprocess communication (IPC) without the need to use AIDL.
+ +Here's a summary of how to use a {@link android.os.Messenger}:
+ +In this way, there are no "methods" for the client to call on the service. Instead, the +client delivers "messages" ({@link android.os.Message} objects) that the service receives in +its {@link android.os.Handler}.
+ +Here's a simple example service that uses a {@link android.os.Messenger} interface:
+ +
+public class MessengerService extends Service {
+ /** Command to the service to display a message */
+ static final int MSG_SAY_HELLO = 1;
+
+ /**
+ * Handler of incoming messages from clients.
+ */
+ class IncomingHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SAY_HELLO:
+ Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ }
+
+ /**
+ * Target we publish for clients to send messages to IncomingHandler.
+ */
+ final Messenger mMessenger = new Messenger(new IncomingHandler());
+
+ /**
+ * When binding to the service, we return an interface to our messenger
+ * for sending messages to the service.
+ */
+ @Override
+ public IBinder onBind(Intent intent) {
+ Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
+ return mMessenger.getBinder();
+ }
+}
+
+
+Notice that the {@link android.os.Handler#handleMessage handleMessage()} method in the +{@link android.os.Handler} is where the service receives the incoming {@link android.os.Message} +and decides what to do, based on the {@link android.os.Message#what} member.
+ +All that a client needs to do is create a {@link android.os.Messenger} based on the {@link +android.os.IBinder} returned by the service and send a message using {@link +android.os.Messenger#send send()}. For example, here's a simple activity that binds to the +service and delivers the {@code MSG_SAY_HELLO} message to the service:
+ +
+public class ActivityMessenger extends Activity {
+ /** Messenger for communicating with the service. */
+ Messenger mService = null;
+
+ /** Flag indicating whether we have called bind on the service. */
+ boolean mBound;
+
+ /**
+ * Class for interacting with the main interface of the service.
+ */
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ // This is called when the connection with the service has been
+ // established, giving us the object we can use to
+ // interact with the service. We are communicating with the
+ // service using a Messenger, so here we get a client-side
+ // representation of that from the raw IBinder object.
+ mService = new Messenger(service);
+ mBound = true;
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been
+ // unexpectedly disconnected -- that is, its process crashed.
+ mService = null;
+ mBound = false;
+ }
+ };
+
+ public void sayHello(View v) {
+ if (!mBound) return;
+ // Create and send a message to the service, using a supported 'what' value
+ Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
+ try {
+ mService.send(msg);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ // Bind to the service
+ bindService(new Intent(this, MessengerService.class), mConnection,
+ Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ // Unbind from the service
+ if (mBound) {
+ unbindService(mConnection);
+ mBound = false;
+ }
+ }
+}
+
+
+Notice that this example does not show how the service can respond to the client. If you want the +service to respond, then you need to also create a {@link android.os.Messenger} in the client. Then +when the client receives the {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()} callback, it sends a {@link android.os.Message} to the service that includes +the client's {@link android.os.Messenger} in the {@link android.os.Message#replyTo} parameter +of the {@link android.os.Messenger#send send()} method.
+ +You can see an example of how to provide two-way messaging in the {@code +MessengerService.java} (service) and {@code +MessengerServiceActivities.java} (client) samples.
+ + + + + +Application components (clients) can bind to a service by calling +{@link android.content.Context#bindService bindService()}. The Android +system then calls the service's {@link android.app.Service#onBind +onBind()} method, which returns an {@link android.os.IBinder} for interacting with the service.
+ +The binding is asynchronous. {@link android.content.Context#bindService +bindService()} returns immediately and does not return the {@link android.os.IBinder} to +the client. To receive the {@link android.os.IBinder}, the client must create an instance of {@link +android.content.ServiceConnection} and pass it to {@link android.content.Context#bindService +bindService()}. The {@link android.content.ServiceConnection} includes a callback method that the +system calls to deliver the {@link android.os.IBinder}.
+ +Note: Only activities, services, and content providers can bind +to a service—you cannot bind to a service from a broadcast receiver.
+ +So, to bind to a service from your client, you must:
+Your implementation must override two callback methods:
+When your client is destroyed, it will unbind from the service, but you should always unbind +when you're done interacting with the service or when your activity pauses so that the service can +shutdown while its not being used. (Appropriate times to bind and unbind is discussed +more below.)
+For example, the following snippet connects the client to the service created above by +extending the Binder class, so all it must do is cast the returned +{@link android.os.IBinder} to the {@code LocalService} class and request the {@code +LocalService} instance:
+ +
+LocalService mService;
+private ServiceConnection mConnection = new ServiceConnection() {
+ // Called when the connection with the service is established
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ // Because we have bound to an explicit
+ // service that is running in our own process, we can
+ // cast its IBinder to a concrete class and directly access it.
+ LocalBinder binder = (LocalBinder) service;
+ mService = binder.getService();
+ mBound = true;
+ }
+
+ // Called when the connection with the service disconnects unexpectedly
+ public void onServiceDisconnected(ComponentName className) {
+ Log.e(TAG, "onServiceDisconnected");
+ mBound = false;
+ }
+};
+
+
+With this {@link android.content.ServiceConnection}, the client can bind to a service by passing +this it to {@link android.content.Context#bindService bindService()}. For example:
+ ++Intent intent = new Intent(this, LocalService.class); +bindService(intent, mConnection, Context.BIND_AUTO_CREATE); ++ +
Here are some important notes about binding to a service:
+Note: You should usually not bind and unbind +during your activity's {@link android.app.Activity#onResume onResume()} and {@link +android.app.Activity#onPause onPause()}, because these callbacks occur at every lifecycle transition +and you should keep the processing that occurs at these transitions to a minimum. Also, if +multiple activities in your application bind to the same service and there is a transition between +two of those activities, the service may be destroyed and recreated as the current activity unbinds +(during pause) before the next one binds (during resume). (This activity transition for how +activities coordinate their lifecycles is described in the Activities +document.)
+For more sample code, showing how to bind to a service, see the {@code +RemoteService.java} class in ApiDemos.
+ + + + + +
+Figure 1. The lifecycle for a service that is started +and also allows binding.
+When a service is unbound from all clients, the Android system destroys it (unless it was also +started with {@link android.app.Service#onStartCommand onStartCommand()}). As such, you don't have +to manage the lifecycle of your service if it's purely a bound +service—the Android system manages it for you based on whether it is bound to any clients.
+ +However, if you choose to implement the {@link android.app.Service#onStartCommand +onStartCommand()} callback method, then you must explicitly stop the service, because the +service is now considered to be started. In this case, the service runs until the service +stops itself with {@link android.app.Service#stopSelf()} or another component calls {@link +android.content.Context#stopService stopService()}, regardless of whether it is bound to any +clients.
+ +Additionally, if your service is started and accepts binding, then when the system calls +your {@link android.app.Service#onUnbind onUnbind()} method, you can optionally return +{@code true} if you would like to receive a call to {@link android.app.Service#onRebind +onRebind()} the next time a client binds to the service (instead of receiving a call to {@link +android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind +onRebind()} returns void, but the client still receives the {@link android.os.IBinder} in its +{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback. +Below, figure 1 illustrates the logic for this kind of lifecycle.
+ +For more information about the lifecycle of an started service, see the Services document.
+ + + + diff --git a/docs/html/guide/topics/fundamentals/services.jd b/docs/html/guide/topics/fundamentals/services.jd new file mode 100644 index 0000000000000..df1eacee50295 --- /dev/null +++ b/docs/html/guide/topics/fundamentals/services.jd @@ -0,0 +1,860 @@ +page.title=Services +parent.title=Application Fundamentals +parent.link=index.html +@jd:body + +A {@link android.app.Service} is an application component that can perform +long-running operations in the background and does not provide a user interface. Another +application component can start a service and it will continue to run in the background even if the +user switches to another application. Additionally, a component can bind to a service to +interact with it and even perform interprocess communication (IPC). For example, a service might +handle network transactions, play music, perform file I/O, or interact with a content provider, all +from the background.
+ +A service can essentially take two forms:
+ +Although this documentation generally discusses these two types of services separately, your +service can work both ways—it can be started (to run indefinitely) and also allow binding. +It's simply a matter of whether you implement a couple callback methods: {@link +android.app.Service#onStartCommand onStartCommand()} to allow components to start it and {@link +android.app.Service#onBind onBind()} to allow binding.
+ +Regardless of whether your application is started, bound, or both, any application component +can use the service (even from a separate application), in the same way that any component can use +an activity—by starting it with an {@link android.content.Intent}. However, you can declare +the service as private, in the manifest file, and block access from other applications. This is +discussed more in the section about Declaring the service in the +manifest.
+ +Caution: A service runs in the +main thread of its hosting process—the service does not create its own thread +and does not run in a separate process (unless you specify otherwise). This means +that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 +playback or networking), you should create a new thread within the service to do that work. By using +a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the +application's main thread can remain dedicated to user interaction with your activities.
+ + +A service is simply a component that can run in the background even when the user is not +interacting with your application. Thus, you should create a service only if that is what you +need.
+If you need to perform work outside your main thread, but only while the user is interacting +with your application, then you should probably instead create a new thread and not a service. For +example, if you want to play some music, but only while your activity is running, you might create +a thread in {@link android.app.Activity#onCreate onCreate()}, start running it in {@link +android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop +onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread}, +instead of the traditional {@link java.lang.Thread} class. See the Processes and +Threading document for more information about threads.
+Remember that if you do use a service, it still runs in your application's main thread by +default, so you should still create a new thread within the service if it performs intensive or +blocking operations.
+To create a service, you must create a subclass of {@link android.app.Service} (or one +of its existing subclasses). In your implementation, you need to override some callback methods that +handle key aspects of the service lifecycle and provide a mechanism for components to bind to +the service, if appropriate. The most important callback methods you should override are:
+ +If a component starts the service by calling {@link +android.content.Context#startService startService()} (which results in a call to {@link +android.app.Service#onStartCommand onStartCommand()}), then the service +remains running until it stops itself with {@link android.app.Service#stopSelf()} or another +component stops it by calling {@link android.content.Context#stopService stopService()}.
+ +If a component calls +{@link android.content.Context#bindService bindService()} to create the service (and {@link +android.app.Service#onStartCommand onStartCommand()} is not called), then the service runs +only as long as the component is bound to it. Once the service is unbound from all clients, the +system destroys it.
+ +The Android system will force-stop a service only when memory is low and it must recover system +resources for the activity that has user focus. If the service is bound to an activity that has user +focus, then it's less likely to be killed, and if the service is declared to run in the foreground (discussed later), then it will almost never be killed. +Otherwise, if the service was started and is long-running, then the system will lower its position +in the list of background tasks over time and the service will become highly susceptible to +killing—if your service is started, then you must design it to gracefully handle restarts +by the system. If the system kills your service, it restarts it as soon as resources become +available again (though this also depends on the value you return from {@link +android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information +about when the system might destroy a service, see the Processes and Threading +document.
+ +In the following sections, you'll see how you can create each type of service and how to use +it from other application components.
+ + + +Like activities (and other components), you must declare all services in your application's +manifest file.
+ +To decalare your service, add a {@code <service>} element +as a child of the {@code <application>} +element. For example:
+ ++<manifest ... > + ... + <application ... > + <service android:name=".ExampleService" /> + ... + </application> +</manifest> ++ +
There are other attributes you can include in the {@code <service>} element to +define properties such as permissions required to start the service and the process in +which the service should run. See the {@code <service>} element +reference for more information.
+ +Just like an activity, a service can define intent filters that allow other components to +invoke the service using implicit intents. By declaring intent filters, components +from any application installed on the user's device can potentially start your service if your +service declares an intent filter that matches the intent another application passes to {@link +android.content.Context#startService startService()}.
+ +If you plan on using your service only locally (other applications do not use it), then you +don't need to (and should not) supply any intent filters. Without any intent filters, you must +start the service using an intent that explicitly names the service class. More information +about starting a service is discussed below.
+ +Additionally, you can ensure that your service is private to your application only if +you include the {@code android:exported} +attribute and set it to {@code "false"}. This is effective even if your service supplies intent +filters.
+ +For more information about creating intent filters for your service, see the Intents and Intent Filters +document.
+ + + +If you're building an application for Android 1.6 or lower, you need +to implement {@link android.app.Service#onStart onStart()}, instead of {@link +android.app.Service#onStartCommand onStartCommand()} (in Android 2.0, +{@link android.app.Service#onStart onStart()} was deprecated in favor of {@link +android.app.Service#onStartCommand onStartCommand()}).
+For more information about providing compatibility with versions of Android older than 2.0, see +the {@link android.app.Service#onStartCommand onStartCommand()} documentation.
+A started service is one that another component starts by calling {@link +android.content.Context#startService startService()}, resulting in a call to the service's +{@link android.app.Service#onStartCommand onStartCommand()} method.
+ +When a service is started, it has a lifecycle that's independent of the +component that started it and the service can run in the background indefinitely, even if +the component that started it is destroyed. As such, the service should stop itself when its job +is done by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can stop it +by calling {@link android.content.Context#stopService stopService()}.
+ +An application component such as an activity can start the service by calling {@link +android.content.Context#startService startService()} and passing an {@link android.content.Intent} +that specifies the service and includes any data for the service to use. The service receives +this {@link android.content.Intent} in the {@link android.app.Service#onStartCommand +onStartCommand()} method.
+ +For instance, suppose an activity needs to save some data to an online database. The activity can +start a companion service and deliver it the data to save by passing an intent to {@link +android.content.Context#startService startService()}. The service receives the intent in {@link +android.app.Service#onStartCommand onStartCommand()}, connects to the Internet and performs the +database transaction. When the transaction is done, the service stops itself and it is +destroyed.
+ +Caution: A services runs in the same process as the application +in which it is declared and in the main thread of that application, by default. So, if your service +performs intensive or blocking operations while the user interacts with an activity from the same +application, the service will slow down activity performance. To avoid impacting application +performance, you should start a new thread inside the service.
+ +Traditionally, there are two classes you can extend to create a started service:
+The following sections describe how you can implement your service using either one for these +classes.
+ + +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 you +implement your service using the {@link android.app.IntentService} class.
+ +The {@link android.app.IntentService} does the following:
+ +All this adds up to the fact that all you need to do is implement {@link +android.app.IntentService#onHandleIntent onHandleIntent()} to do the work provided by the +client. (Though, you also need to provide a small constructor for the service.)
+ +Here's an example implementation of {@link android.app.IntentService}:
+ +
+public class HelloIntentService extends IntentService {
+
+ /**
+ * A constructor is required, and must call the super {@link android.app.IntentService#IntentService}
+ * 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) {
+ }
+ }
+ }
+ }
+}
+
+
+That's all you need: a constructor and an implementation of {@link +android.app.IntentService#onHandleIntent onHandleIntent()}.
+ +If you decide to also override other callback methods, such as {@link +android.app.IntentService#onCreate onCreate()}, {@link +android.app.IntentService#onStartCommand onStartCommand()}, or {@link +android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation, so +that the {@link android.app.IntentService} can properly handle the life of the worker thread.
+ +For example, {@link android.app.IntentService#onStartCommand onStartCommand()} must return +the default implementation (which is how the intent gets delivered to {@link +android.app.IntentService#onHandleIntent onHandleIntent()}):
+ +
+@Override
+public int onStartCommand(Intent intent, int flags, int startId) {
+ Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
+ return super.onStartCommand(intent,flags,startId);
+}
+
+
+Besides {@link android.app.IntentService#onHandleIntent onHandleIntent()}, the only method +from which you don't need to call the super class is {@link android.app.IntentService#onBind +onBind()} (but you only need to implement that if your service allows binding).
+ +In the next section, you'll see how the same kind of service is implemented when extending +the base {@link android.app.Service} class, which is a lot more code, but which might be +appropriate if you need to handle simultaneous start requests.
+ + +As you saw in the previous section, using {@link android.app.IntentService} makes your +implementation of a started service very simple. If, however, you require your service to +perform multi-threading (instead of processing start requests through a work queue), then you +can extend the {@link android.app.Service} class to handle each intent.
+ +For comparison, the following example code is an implementation of the {@link +android.app.Service} class that performs the exact same work as the example above using {@link +android.app.IntentService}. That is, for each start request, it uses a worker thread to perform the +job and processes only one request at a time.
+ +
+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();
+ }
+}
+
+
+As you can see, it's a lot more work than using {@link android.app.IntentService}.
+ +However, because you handle each call to {@link android.app.Service#onStartCommand +onStartCommand()} yourself, you can perform multiple requests simultaneously. That's not what +this example does, but if that's what you want, then you can create a new thread for each +request and run them right away (instead of waiting for the previous request to finish).
+ +Notice that the {@link android.app.Service#onStartCommand onStartCommand()} method must return an +integer. The integer is a value that describes how the system should continue the service in the +event that the system kills it (as discussed above, the default implementation for {@link +android.app.IntentService} handles this for you, though you are able to modify it). The return value +from {@link android.app.Service#onStartCommand onStartCommand()} must be one of the following +constants:
+ +For more details about these return values, see the linked reference documentation for each +constant.
+ + + +You can start a service from an activity or other application component by passing an +{@link android.content.Intent} (specifying the service to start) to {@link +android.content.Context#startService startService()}. The Android system calls the service's {@link +android.app.Service#onStartCommand onStartCommand()} method and passes it the {@link +android.content.Intent}. (You should never call {@link android.app.Service#onStartCommand +onStartCommand()} directly.)
+ +For example, an activity can start the example service in the previous section ({@code +HelloSevice}) using an explicit intent with {@link android.content.Context#startService +startService()}:
+ ++Intent intent = new Intent(this, HelloService.class); +startService(intent); ++ +
The {@link android.content.Context#startService startService()} method returns immediately and +the Android system calls the service's {@link android.app.Service#onStartCommand +onStartCommand()} method. If the service is not already running, the system first calls {@link +android.app.Service#onCreate onCreate()}, then calls {@link android.app.Service#onStartCommand +onStartCommand()}.
+ +If the service does not also provide binding, the intent delivered with {@link +android.content.Context#startService startService()} is the only mode of communication between the +application component and the service. However, if you want the service to send a result back, then +the client that starts the service can create a {@link android.app.PendingIntent} for a broadcast +(with {@link android.app.PendingIntent#getBroadcast getBroadcast()}) and deliver it to the service +in the {@link android.content.Intent} that starts the service. The service can then use the +broadcast to deliver a result.
+ +Multiple requests to start the service result in multiple corresponding calls to the service's +{@link android.app.Service#onStartCommand onStartCommand()}. However, only one request to stop +the service (with {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}) is required to stop it.
+ + +A started service must manage its own lifecycle. That is, the system does not stop or +destroy the service unless it must recover system memory and the service +continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. So, +the service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()} or another +component can stop it by calling {@link android.content.Context#stopService stopService()}.
+ +Once requested to stop with {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}, the system destroys the service as soon as +possible.
+ +However, if your service handles multiple requests to {@link
+android.app.Service#onStartCommand onStartCommand()} concurrently, then you shouldn't stop the
+service when you're done processing a start request, because you might have since received a new
+start request (stopping at the end of the first request would terminate the second one). To avoid
+this problem, you can use {@link android.app.Service#stopSelf(int)} to ensure that your request to
+stop the service is always based on the most recent start request. That is, when you call {@link
+android.app.Service#stopSelf(int)}, you pass the ID of the start request (the startId
+delivered to {@link android.app.Service#onStartCommand onStartCommand()}) to which your stop request
+corresponds. Then if the service received a new start request before you were able to call {@link
+android.app.Service#stopSelf(int)}, then the ID will not match and the service will not stop.
Caution: It's important that your application stops its services +when it's done working, to avoid wasting system resources and consuming battery power. If necessary, +other components can stop the service by calling {@link +android.content.Context#stopService stopService()}. Even if you enable binding for the service, +you must always stop the service yourself if it ever received a call to {@link +android.app.Service#onStartCommand onStartCommand()}.
+ +For more information about the lifecycle of a service, see the section below about Managing the Lifecycle of a Service.
+ + + +A bound service is one that allows application components to bind to it by calling {@link +android.content.Context#bindService bindService()} in order to create a long-standing connection +(and generally does not allow components to start it by calling {@link +android.content.Context#startService startService()}).
+ +You should create a bound service when you want to interact with the service from activities +and other components in your application or to expose some of your application's functionality to +other applications, through interprocess communication (IPC).
+ +To create a bound service, you must implement the {@link +android.app.Service#onBind onBind()} callback method to return an {@link android.os.IBinder} that +defines the interface for communication with the service. Other application components can then call +{@link android.content.Context#bindService bindService()} to retrieve the interface and +begin calling methods on the service. The service lives only to serve the application component that +is bound to it, so when there are no components bound to the service, the system destroys it +(you do not need to stop a bound service in the way you must when the service is started +through {@link android.app.Service#onStartCommand onStartCommand()}).
+ +To create a bound service, the first thing you must do is define the interface that specifies +how a client can communicate with the service. This interface between the service +and a client must be an implementation of {@link android.os.IBinder} and is what your service must +return from the {@link android.app.Service#onBind +onBind()} callback method. Once the client receives the {@link android.os.IBinder}, it can begin +interacting with the service through that interface.
+ +Multiple clients can bind to the service at once. When a client is done interacting with the +service, it calls {@link android.content.Context#unbindService unbindService()} to unbind. Once +there are no clients bound to the service, the system destroys the service.
+ +There are multiple ways to implement a bound service and the implementation is more +complicated than a started service, so the bound service discussion appears in a separate +document about Bound Services.
+ + + +Once running, a service can notify the user of events using Toast Notifications or Status Bar Notifications.
+ +A toast notification is a message that appears on the surface of the current window for a +moment then disappears, while a status bar notification provides an icon in the status bar with a +message, which the user can select in order to take an action (such as start an activity).
+ +Usually, a status bar notification is the best technique when some background work has completed +(such as a file completed +downloading) and the user can now act on it. When the user selects the notification from the +expanded view, the notification can start an activity (such as to view the downloaded file).
+ +See the Toast Notifications or Status Bar Notifications +developer guides for more information.
+ + + +A foreground service is a service that's considered to be something the +user is actively aware of and thus not a candidate for the system to kill when low on memory. A +foreground service must provide a notification for the status bar, which is placed under the +"Ongoing" heading, which means that the notification cannot be dismissed unless the service is +either stopped or removed from the foreground.
+ +For example, a music player that plays music from a service should be set to run in the +foreground, because the user it explicitly aware +of its operation. The notification in the status bar might indicate the current song and allow +the user to launch an activity to interact with the music player.
+ +To request that your service run in the foreground, call {@link +android.app.Service#startForeground startForeground()}. This method takes two parameters: an integer +that uniquely identifies the notification and the {@link +android.app.Notification} for the status bar. For example:
+ ++Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), + System.currentTimeMillis()); +Intent notificationIntent = new Intent(this, ExampleActivity.class); +PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); +notification.setLatestEventInfo(this, getText(R.string.notification_title), + getText(R.string.notification_message), pendingIntent); +startForeground(ONGOING_NOTIFICATION, notification); ++ + +
To remove the service from the foreground, call {@link +android.app.Service#stopForeground stopForeground()}. This method takes a boolean, indicating +whether to remove the status bar notification as well. This method does not stop the +service. However, if you stop the service while it's still running in the foreground, then the +notification is also removed.
+ +Note: The methods {@link +android.app.Service#startForeground startForeground()} and {@link +android.app.Service#stopForeground stopForeground()} were introduced in Android 2.0 (API Level +5). In order to run your service in the foreground on older versions of the platform, you must +use the previous {@code setForeground()} method—see the {@link +android.app.Service#startForeground startForeground()} documentation for information about how +to provide backward compatibility.
+ +For more information about notifications, see Creating Status Bar +Notifications.
+ + + +The lifecycle of a service is much simpler than that of an activity. However, it's even more important +that you pay close attention to how your service is created and destroyed, because a service +can run in the background without the user being aware.
+ +The service lifecycle—from when it's created to when it's destroyed—can follow two +different paths:
+ +The service is created when another component calls {@link +android.content.Context#startService startService()}. The service then runs indefinitely and must +stop itself by calling {@link +android.app.Service#stopSelf() stopSelf()}. Another component can also stop the +service by calling {@link android.content.Context#stopService +stopService()}. When the service is stopped, the system destroys it..
The service is created when another component (a client) calls {@link +android.content.Context#bindService bindService()}. The client then communicates with the service +through an {@link android.os.IBinder} interface. The client can close the connection by calling +{@link android.content.Context#unbindService unbindService()}. Multiple clients can bind to +the same service and when all of them unbind, the system destroys the service. (The service +does not need to stop itself.)
These two paths are not entirely separate. That is, you can bind to a service that was already +started with {@link android.content.Context#startService startService()}. For example, a background +music service could be started by calling {@link android.content.Context#startService +startService()} with an {@link android.content.Intent} that identifies the music to play. Later, +possibly when the user wants to exercise some control over the player or get information about the +current song, an activity can bind to the service by calling {@link +android.content.Context#bindService bindService()}. In cases like this, {@link +android.content.Context#stopService stopService()} or {@link android.app.Service#stopSelf +stopSelf()} does not actually stop the service until all clients unbind.
+ + +Like an activity, a service has lifecycle callback methods that you can implement to monitor +changes in the service's state and perform work at the appropriate times. The following skeleton +service demonstrates each of the lifecycle methods:
+ + +
+Figure 2. The service lifecycle. The diagram on the left +shows the lifecycle when the service is created with {@link android.content.Context#startService +startService()} and the diagram on the right shows the lifecycle when the service is created +with {@link android.content.Context#bindService bindService()}.
+
+public class ExampleService extends Service {
+ int mStartMode; // indicates how to behave if the service is killed
+ IBinder mBinder; // interface for clients that bind
+ boolean mAllowRebind; // indicates whether onRebind should be used
+
+ @Override
+ public void {@link android.app.Service#onCreate onCreate}() {
+ // The service is being created
+ }
+ @Override
+ public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) {
+ // The service is starting, due to a call to {@link android.content.Context#startService startService()}
+ return mStartMode;
+ }
+ @Override
+ public IBinder {@link android.app.Service#onBind onBind}(Intent intent) {
+ // A client is binding to the service with {@link android.content.Context#bindService bindService()}
+ return mBinder;
+ }
+ @Override
+ public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
+ // All clients have unbound with {@link android.content.Context#unbindService unbindService()}
+ return mAllowRebind;
+ }
+ @Override
+ public void {@link android.app.Service#onRebind onRebind}(Intent intent) {
+ // A client is binding to the service with {@link android.content.Context#bindService bindService()},
+ // after onUnbind() has already been called
+ }
+ @Override
+ public void {@link android.app.Service#onDestroy onDestroy}() {
+ // The service is no longer used and is being destroyed
+ }
+}
+
+
+Note: Unlike the activity lifecycle callback methods, you are +not required to call the superclass implementation of these callback methods.
+ +By implementing these methods, you can monitor two nested loops of the service's lifecycle:
+ +The {@link android.app.Service#onCreate onCreate()} and {@link android.app.Service#onDestroy +onDestroy()} methods are called for all services, whether +they're created by {@link android.content.Context#startService startService()} or {@link +android.content.Context#bindService bindService()}.
If the service is started, the active lifetime ends the same time that the entire lifetime +ends (the service is still active even after {@link android.app.Service#onStartCommand +onStartCommand()} returns). If the service is bound, the active lifetime ends when {@link +android.app.Service#onUnbind onUnbind()} returns.
+Note: Although a started service is stopped by a call to +either {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}, there is not a respective callback for the +service (there's no {@code onStop()} callback). So, unless the service is bound to a client, +the system destroys it when the service is stopped—{@link +android.app.Service#onDestroy onDestroy()} is the only callback received.
+ +Figure 2 illustrates the typical callback methods for a service. Although the figure separates +services that are created by {@link android.content.Context#startService startService()} from those +created by {@link android.content.Context#bindService bindService()}, keep +in mind that any service, no matter how it's started, can potentially allow clients to bind to it. +So, a service that was initially started with {@link android.app.Service#onStartCommand +onStartCommand()} (by a client calling {@link android.content.Context#startService startService()}) +can still receive a call to {@link android.app.Service#onBind onBind()} (when a client calls +{@link android.content.Context#bindService bindService()}).
+ +For more information about creating a service that provides binding, see the Bound Services document, +which includes more information about the {@link android.app.Service#onRebind onRebind()} +callback method in the section about Managing the Lifecycle of +a Bound Service.
+ + + +To learn how to query data from the system or other applications (such as contacts or media +stored on the device), continue with the Content Providers +document.
diff --git a/docs/html/images/fundamentals/service_binding_tree_lifecycle.png b/docs/html/images/fundamentals/service_binding_tree_lifecycle.png new file mode 100644 index 0000000000000..46d2df50e85a3 Binary files /dev/null and b/docs/html/images/fundamentals/service_binding_tree_lifecycle.png differ diff --git a/docs/html/images/service_lifecycle.png b/docs/html/images/service_lifecycle.png index 0748db280183e..f9602f84a93a7 100644 Binary files a/docs/html/images/service_lifecycle.png and b/docs/html/images/service_lifecycle.png differ