cherrypick Change-Id: I1365c6c45f8e1f75ee4afbc52c32778d21b97be4 from master
docs: Rewrite of App Fundamentals.. Part 2. This introduces three new docs: Services: Provides an introduction to using services and describes the service lifecycle (previously in the "Component Lifecycles" section of the fundamentals.jd document) Bound Services: A guide for services that offer binding. AIDL: A doc about using AIDL (primarily for creating a service interface) Also includes edits to IntentService javadocs to clarify different behaviors for some callback methods Includes a new version of the services lifecycle diagram and an additional diagram for determining onRebind() These files are orphaned for now---they're not linked in the sidenav, until I get the last couple documents submitted for the app fundamentals. Change-Id: I7fb0a8faff1f18b7d6b9a7b59f66f55a1b6168f1
This commit is contained in:
@@ -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)}.
|
||||
|
||||
387
docs/html/guide/topics/advanced/aidl.jd
Normal file
387
docs/html/guide/topics/advanced/aidl.jd
Normal file
@@ -0,0 +1,387 @@
|
||||
page.title=Android Interface Definition Language (AIDL)
|
||||
@jd:body
|
||||
|
||||
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> 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 <a href="Binder">implementing a
|
||||
Binder</a> or, if you want to perform IPC, but do not need to handle multithreading, then you
|
||||
should implement your interface <a href="#Messenger">using a Messenger</a>.</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<ul>
|
||||
<li>Calls from the local process are executed in the same thread that is making the call. If this is
|
||||
your main UI thread, that thread will continue executing into the aidl interface. If it is another
|
||||
thread, that is one that will be executing your code. Thus if only local threads are accessing the
|
||||
interface, you can completely control which threads are executing in it (but if that is the case,
|
||||
why are you defining an aidl interface at all?).</li>
|
||||
|
||||
<li>Calls from a remote process are dispatched from a thread pool the platform maintains inside of
|
||||
your own process. You must be prepared for incoming calls from unknown threads, with multiple calls
|
||||
happening at the same time. In other words, an implementation of an aidl interface must be
|
||||
completely thread-safe.</li>
|
||||
|
||||
<li>The "oneway" keyword modifies the behavior of remote calls. When used, a remote call will not
|
||||
block until its call completes; it simply sends the transaction data and immediately returns. The
|
||||
implementation of the interface will eventually receive this as a regular call from the {@link
|
||||
android.os.Binder} thread pool as a normal remote call. If "oneway" is used with a local call,
|
||||
there is no impact and the call is still synchronous.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2 id="Defining">Defining an AIDL Interface</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>To create a bounded service using AIDL, follow these steps:</p>
|
||||
<ol>
|
||||
<li><a href="#CreateAidl">Create the .aidl file</a>
|
||||
<p>This file defines the programming interface with method signatures.</p>
|
||||
</li>
|
||||
<li><a href="#ImplementTheInterface">Implement the interface</a>
|
||||
<p>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.</p>
|
||||
</li>
|
||||
<li><a href="#ExposeTheInterface">Expose the interface to clients</a>
|
||||
<p>Implement a {@link android.app.Service Service} and override {@link
|
||||
android.app.Service#onBind onBind()} to return your implementation of the {@code Stub}
|
||||
class.</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p class="caution"><strong>Caution:</strong> 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.</p>
|
||||
|
||||
|
||||
<h3 id="CreateAidl">1. Create the .aidl file</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>By default, AIDL supports the following data types:</p>
|
||||
|
||||
<ul>
|
||||
<li>All primitive types in the Java programming language ({@code int}, {@code long}, {@code
|
||||
char}, {@code boolean}, etc.)</li>
|
||||
<li>{@link java.lang.String}</li>
|
||||
<li>{@link java.lang.CharSequence}</li>
|
||||
<li>{@link java.util.List}
|
||||
<p>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. <code>List<String></code>).
|
||||
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.</p>
|
||||
</li>
|
||||
<li>{@link java.util.Map}
|
||||
<p>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.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>When defining methods for your service interface, be aware that:</p>
|
||||
<ul>
|
||||
<li>Methods can take zero or more parameters, and return a value or void.</li>
|
||||
<li>All non-primitive parameters require a directional tag indicating which way the data will go.
|
||||
Either <code>in</code>, <code>out</code>, or <code>inout</code> (see the example below).
|
||||
<p>Primitives are <code>in</code> by default, and cannot be otherwise.</p>
|
||||
<p class="caution"><strong>Caution:</strong> You should limit the direction to what is truly
|
||||
needed, because marshalling parameters is expensive.</p></li>
|
||||
<li>All code comments included in the {@code .aidl} file are included in the generated {@link
|
||||
android.os.IBinder} interface (except for comments before the import and package
|
||||
statements).</li>
|
||||
</ul>
|
||||
|
||||
<p>Here is an example {@code .aidl} file:</p>
|
||||
|
||||
<pre>
|
||||
// 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);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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}).</p>
|
||||
|
||||
<p>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 <code>ant debug</code> (or <code>ant
|
||||
release</code>) as soon as you're finished writing the {@code .aidl} file, so that your code can
|
||||
link against the generated class.</p>
|
||||
|
||||
|
||||
<h3 id="ImplementTheInterface">2. Implement the interface</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> {@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 <a href="#calling">Calling an IPC
|
||||
Method</a> for more details on how to make this cast.</p></p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Here is an example implementation of an interface called {@code IRemoteService} (defined by the
|
||||
{@code IRemoteService.aidl} example, above) using an anonymous instance:</p>
|
||||
|
||||
<pre>
|
||||
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
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>There are a few rules you should be aware of when implementing your AIDL interface: </p>
|
||||
<ul>
|
||||
<li>Incoming calls are not guaranteed to be executed on the main thread, so you need to think
|
||||
about multithreading from the start and properly build your service to be thread-safe.</li>
|
||||
<li>By default, RPC calls are synchronous. If you know that the service takes more than a few
|
||||
milliseconds to complete a request, you should not call it from the activity's main thread, because
|
||||
it might hang the application (Android might display an "Application is Not Responding"
|
||||
dialog)—you should usually call them from a separate thread in the client. </li>
|
||||
<li>No exceptions that you throw are sent back to the caller.</li>
|
||||
<li>Only methods are supported; you cannot expose static fields in AIDL.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3 id="ExposeTheInterface">3. Expose the interface to clients</h3>
|
||||
|
||||
<p>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. </p>
|
||||
|
||||
<pre>
|
||||
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
|
||||
}
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>When the client receives the {@link android.os.IBinder} in the {@link
|
||||
android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback, it must call
|
||||
<code><em>YourServiceInterface</em>.Stub.asInterface(service)</code> to cast the returned
|
||||
parameter to <code><em>YourServiceInterface</em></code> type. For example:</p>
|
||||
|
||||
<pre>
|
||||
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");
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p>For more sample code, see the <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
|
||||
RemoteService.java}</a> class in <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="PassingObjects">Passing Objects over IPC</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>There are five parts to making a class support the {@link android.os.Parcelable} protocol:</b>
|
||||
<ol>
|
||||
<li>Make your class implement the {@link android.os.Parcelable} interface.</li>
|
||||
<li>Implement {@link android.os.Parcelable#writeToParcel writeToParcel}, which takes the
|
||||
current state of the object and writes it to a {@link android.os.Parcel}.</li>
|
||||
<li>Add a static field called <code>CREATOR</code> to your class which is an object implementing
|
||||
the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.</li>
|
||||
<li>Finally, create an {@code .aidl} file that declares your parcelable class (as shown for the
|
||||
{@code Rect.aidl} file, below).
|
||||
<p>If you are using a custom build process, do <em>not</em> add the {@code .aidl} file to your
|
||||
build. Similar to a header file in the C language, this {@code .aidl} file isn't compiled.</p></li>
|
||||
</ol>
|
||||
|
||||
<p>AIDL will use these methods and fields in the code it generates to marshall and unmarshall
|
||||
your objects.</p>
|
||||
|
||||
<p>For example, here is a {@code Rect.aidl} file to create a {@code Rect} class that's
|
||||
parcelable:</p>
|
||||
|
||||
<pre>
|
||||
package android.graphics;
|
||||
|
||||
// Declare Rect so AIDL can find it and knows that it implements
|
||||
// the parcelable protocol.
|
||||
parcelable Rect;
|
||||
</pre>
|
||||
|
||||
<p>And here is an example of how the {@link android.graphics.Rect} class implements the
|
||||
{@link android.os.Parcelable} protocol.</p>
|
||||
|
||||
<pre>
|
||||
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();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p class="warning"><strong>Warning:</strong> 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 <a
|
||||
href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> for more
|
||||
information about how to keep your application secure from malware.</p>
|
||||
|
||||
675
docs/html/guide/topics/fundamentals/bound-services.jd
Normal file
675
docs/html/guide/topics/fundamentals/bound-services.jd
Normal file
@@ -0,0 +1,675 @@
|
||||
page.title=Bound Services
|
||||
parent.title=Services
|
||||
parent.link=services.html
|
||||
@jd:body
|
||||
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<ol id="qv">
|
||||
<h2>Quickview</h2>
|
||||
<ul>
|
||||
<li>A bound service allows other components to bind to it, in order to interact with it and
|
||||
perform interprocess communication</li>
|
||||
<li>A bound service is destroyed once all clients unbind, unless the service was also started</li>
|
||||
</ul>
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<li><a href="#Basics">The Basics</a></li>
|
||||
<li><a href="#Creating">Creating a Bound Service</a>
|
||||
<ol>
|
||||
<li><a href="#Binder">Extending the Binder class</a></li>
|
||||
<li><a href="#Messenger">Using a Messenger</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#Binding">Binding to a Service</a></li>
|
||||
<li><a href="#Lifecycle">Managing the Lifecycle of a Bound Service</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Key classes</h2>
|
||||
<ol>
|
||||
<li>{@link android.app.Service}</li>
|
||||
<li>{@link android.content.ServiceConnection}</li>
|
||||
<li>{@link android.os.IBinder}</li>
|
||||
</ol>
|
||||
|
||||
<h2>Samples</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
|
||||
RemoteService}</a></li>
|
||||
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
|
||||
LocalService}</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>See also</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 <a
|
||||
href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> 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.</p>
|
||||
|
||||
|
||||
<h2 id="Basics">The Basics</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<div class="sidebox-wrapper">
|
||||
<div class="sidebox">
|
||||
<h3>Binding to a Started Service</h3>
|
||||
|
||||
<p>As discussed in the <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a>
|
||||
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()}.
|
||||
<p>If you do allow your service to be started and bound, then when the service has been
|
||||
started, the system does <em>not</em> 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()}.</p>
|
||||
|
||||
<p>Although you should usually implement either {@link android.app.Service#onBind onBind()}
|
||||
<em>or</em> {@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.</p>
|
||||
|
||||
<p>Be sure to read the section about <a href="#Lifecycle">Managing the Lifecycle of a Bound
|
||||
Service</a>, for more information about the service lifecycle when adding binding to a
|
||||
started service.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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()}).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="Creating">Creating a Bound Service</h2>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<dl>
|
||||
<dt><a href="#Binder">Extending the Binder class</a></dt>
|
||||
<dd>If your service is private to your own application and runs in the same process as the client
|
||||
(which is common), you should create your interface by extending the {@link android.os.Binder} class
|
||||
and returning an instance of it from
|
||||
{@link android.app.Service#onBind onBind()}. The client receives the {@link android.os.Binder} and
|
||||
can use it to directly access public methods available in either the {@link android.os.Binder}
|
||||
implementation or even the {@link android.app.Service}.
|
||||
<p>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.</dd>
|
||||
|
||||
<dt><a href="#Messenger">Using a Messenger</a></dt>
|
||||
<dd>If you need your interface to work across different processes, you can create
|
||||
an interface for the service with a {@link android.os.Messenger}. In this manner, the service
|
||||
defines a {@link android.os.Handler} that responds to different types of {@link
|
||||
android.os.Message} objects. This {@link android.os.Handler}
|
||||
is the basis for a {@link android.os.Messenger} that can then share an {@link android.os.IBinder}
|
||||
with the client, allowing the client to send commands to the service using {@link
|
||||
android.os.Message} objects. Additionally, the client can define a {@link android.os.Messenger} of
|
||||
its own so the service can send messages back.
|
||||
<p>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.</p>
|
||||
</dd>
|
||||
|
||||
<dt>Using AIDL</dt>
|
||||
<dd>AIDL (Android Interface Definition Language) performs all the work to decompose objects into
|
||||
primitives that the operating system can understand and marshall them across processes to perform
|
||||
IPC. The previous technique, using a {@link android.os.Messenger}, is actually based on AIDL as
|
||||
its underlying structure. As mentioned above, the {@link android.os.Messenger} creates a queue of
|
||||
all the client requests in a single thread, so the service receives requests one at a time. If,
|
||||
however, you want your service to handle multiple requests simultaneously, then you can use AIDL
|
||||
directly. In this case, your service must be capable of multi-threading and be built thread-safe.
|
||||
<p>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.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p class="note"><strong>Note:</strong> Most applications <strong>should not</strong> 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 <a href="{@docRoot}guide/topics/advanced/aidl.html">AIDL</a>
|
||||
document.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 id="Binder">Extending the Binder class</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> 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.</p>
|
||||
|
||||
<p>Here's how to set it up:</p>
|
||||
<ol>
|
||||
<li>In your service, create an instance of {@link android.os.Binder} that either:
|
||||
<ul>
|
||||
<li>contains public methods that the client can call</li>
|
||||
<li>returns the current {@link android.app.Service} instance, which has public methods the
|
||||
client can call</li>
|
||||
<li>or, returns an instance of another class hosted by the service with public methods the
|
||||
client can call</li>
|
||||
</ul>
|
||||
<li>Return this instance of {@link android.os.Binder} from the {@link
|
||||
android.app.Service#onBind onBind()} callback method.</li>
|
||||
<li>In the client, receive the {@link android.os.Binder} from the {@link
|
||||
android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method and
|
||||
make calls to the bound service using the methods provided.</li>
|
||||
</ol>
|
||||
|
||||
<p class="note"><strong>Note:</strong> 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.</p>
|
||||
|
||||
<p>For example, here's a service that provides clients access to methods in the service through
|
||||
a {@link android.os.Binder} implementation:</p>
|
||||
|
||||
<pre>
|
||||
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);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Here's an activity that binds to {@code LocalService} and calls {@code getRandomNumber()}
|
||||
when a button is clicked:</p>
|
||||
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> 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).</p>
|
||||
|
||||
<p>For more sample code, see the <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
|
||||
LocalService.java}</a> class and the <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code
|
||||
LocalServiceActivities.java}</a> class in <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 id="Messenger">Using a Messenger</h3>
|
||||
|
||||
<div class="sidebox-wrapper">
|
||||
<div class="sidebox">
|
||||
<h4>Compared to AIDL</h4>
|
||||
<p>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.</p>
|
||||
<p>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 <a
|
||||
href="{@docRoot}guide/topics/advanced/aidl.html">AIDL</a> to define your interface.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Here's a summary of how to use a {@link android.os.Messenger}:</p>
|
||||
|
||||
<ul>
|
||||
<li>The service implements a {@link android.os.Handler} that receives a callback for each
|
||||
call from a client.</li>
|
||||
<li>The {@link android.os.Handler} is used to create a {@link android.os.Messenger} object
|
||||
(which is a reference to the {@link android.os.Handler}).</li>
|
||||
<li>The {@link android.os.Messenger} creates an {@link android.os.IBinder} that the service
|
||||
returns to clients from {@link android.app.Service#onBind onBind()}.</li>
|
||||
<li>Clients use the {@link android.os.IBinder} to instantiate the {@link android.os.Messenger}
|
||||
(that references the service's {@link android.os.Handler}), which the client uses to send
|
||||
{@link android.os.Message} objects to the service.</li>
|
||||
<li>The service receives each {@link android.os.Message} in its {@link
|
||||
android.os.Handler}—specifically, in the {@link android.os.Handler#handleMessage
|
||||
handleMessage()} method.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>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}.</p>
|
||||
|
||||
<p>Here's a simple example service that uses a {@link android.os.Messenger} interface:</p>
|
||||
|
||||
<pre>
|
||||
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();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>You can see an example of how to provide two-way messaging in the <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code
|
||||
MessengerService.java}</a> (service) and <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code
|
||||
MessengerServiceActivities.java}</a> (client) samples.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="Binding">Binding to a Service</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>The binding is asynchronous. {@link android.content.Context#bindService
|
||||
bindService()} returns immediately and does <em>not</em> 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}.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> Only activities, services, and content providers can bind
|
||||
to a service—you <strong>cannot</strong> bind to a service from a broadcast receiver.</p>
|
||||
|
||||
<p>So, to bind to a service from your client, you must: </p>
|
||||
<ol>
|
||||
<li>Implement {@link android.content.ServiceConnection}.
|
||||
<p>Your implementation must override two callback methods:</p>
|
||||
<dl>
|
||||
<dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt>
|
||||
<dd>The system calls this to deliver the {@link android.os.IBinder} returned by
|
||||
the service's {@link android.app.Service#onBind onBind()} method.</dd>
|
||||
<dt>{@link android.content.ServiceConnection#onServiceDisconnected
|
||||
onServiceDisconnected()}</dt>
|
||||
<dd>The Android system calls this when the connection to the service is unexpectedly
|
||||
lost, such as when the service has crashed or has been killed. This is <em>not</em> called when the
|
||||
client unbinds.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>Call {@link
|
||||
android.content.Context#bindService bindService()}, passing the {@link
|
||||
android.content.ServiceConnection} implementation. </li>
|
||||
<li>When the system calls your {@link android.content.ServiceConnection#onServiceConnected
|
||||
onServiceConnected()} callback method, you can begin making calls to the service, using
|
||||
the methods defined by the interface.</li>
|
||||
<li>To disconnect from the service, call {@link
|
||||
android.content.Context#unbindService unbindService()}.
|
||||
<p>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.)</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>For example, the following snippet connects the client to the service created above by
|
||||
<a href="#Binder">extending the Binder class</a>, so all it must do is cast the returned
|
||||
{@link android.os.IBinder} to the {@code LocalService} class and request the {@code
|
||||
LocalService} instance:</p>
|
||||
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre>
|
||||
Intent intent = new Intent(this, LocalService.class);
|
||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
</pre>
|
||||
|
||||
<ul>
|
||||
<li>The first parameter of {@link android.content.Context#bindService bindService()} is an
|
||||
{@link android.content.Intent} that explicitly names the service to bind (thought the intent
|
||||
could be implicit).</li>
|
||||
<li>The second parameter is the {@link android.content.ServiceConnection} object.</li>
|
||||
<li>The third parameter is a flag indicating options for the binding. It should usually be {@link
|
||||
android.content.Context#BIND_AUTO_CREATE} in order to create the service if its not already alive.
|
||||
Other possible values are {@link android.content.Context#BIND_DEBUG_UNBIND}
|
||||
and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>Additional notes</h3>
|
||||
|
||||
<p>Here are some important notes about binding to a service:</p>
|
||||
<ul>
|
||||
<li>You should always trap {@link android.os.DeadObjectException} exceptions, which are thrown
|
||||
when the connection has broken. This is the only exception thrown by remote methods.</li>
|
||||
<li>Objects are reference counted across processes. </li>
|
||||
<li>You should usually pair the binding and unbinding during
|
||||
matching bring-up and tear-down moments of the client's lifecycle. For example:
|
||||
<ul>
|
||||
<li>If you only need to interact with the service while your activity is visible, you
|
||||
should bind during {@link android.app.Activity#onStart onStart()} and unbind during {@link
|
||||
android.app.Activity#onStop onStop()}.</li>
|
||||
<li>If you want your activity to receive responses even while it is stopped in the
|
||||
background, then you can bind during {@link android.app.Activity#onCreate onCreate()} and unbind
|
||||
during {@link android.app.Activity#onDestroy onDestroy()}. Beware that this implies that your
|
||||
activity needs to use the service the entire time it's running (even in the background), so if
|
||||
the service is in another process, then you increase the weight of the process and it becomes
|
||||
more likely that the system will kill it.</li>
|
||||
</ul>
|
||||
<p class="note"><strong>Note:</strong> You should usually <strong>not</strong> 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 <a
|
||||
href="{@docRoot}guide/topics/fundamentals/activities.html#CoordinatingActivities">Activities</a>
|
||||
document.)</p>
|
||||
</ul>
|
||||
|
||||
<p>For more sample code, showing how to bind to a service, see the <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
|
||||
RemoteService.java}</a> class in <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="Lifecycle">Managing the Lifecycle of a Bound Service</h2>
|
||||
|
||||
<div class="figure" style="width:588px">
|
||||
<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
|
||||
<p class="img-caption"><strong>Figure 1.</strong> The lifecycle for a service that is started
|
||||
and also allows binding.</p>
|
||||
</div>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 <em>started</em>. 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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>For more information about the lifecycle of an started service, see the <a
|
||||
href="{@docRoot}guide/topics/fundamentals/services.html#Lifecycle">Services</a> document.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
860
docs/html/guide/topics/fundamentals/services.jd
Normal file
860
docs/html/guide/topics/fundamentals/services.jd
Normal file
@@ -0,0 +1,860 @@
|
||||
page.title=Services
|
||||
parent.title=Application Fundamentals
|
||||
parent.link=index.html
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<ol id="qv">
|
||||
<h2>Quickview</h2>
|
||||
<ul>
|
||||
<li>A service can run in the background to perform work even while the user is in a different
|
||||
application</li>
|
||||
<li>A service can allow other components to bind to it, in order to interact with it and
|
||||
perform interprocess communication</li>
|
||||
<li>A service runs in the main thread of the application that hosts it, by default</li>
|
||||
</ul>
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<li><a href="#Basics">The Basics</a></li>
|
||||
<ol>
|
||||
<li><a href="#Declaring">Declaring a service in the manifest</a></li>
|
||||
</ol>
|
||||
<li><a href="#CreatingAService">Creating a Started Service</a>
|
||||
<ol>
|
||||
<li><a href="#ExtendingIntentService">Extending the IntentService class</a></li>
|
||||
<li><a href="#ExtendingService">Extending the Service class</a></li>
|
||||
<li><a href="#StartingAService">Starting a service</a></li>
|
||||
<li><a href="#Stopping">Stopping a service</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#CreatingBoundService">Creating a Bound Service</a></li>
|
||||
<li><a href="#Notifications">Sending Notifications to the User</a></li>
|
||||
<li><a href="#Foreground">Running a Service in the Foreground</a></li>
|
||||
<li><a href="#Lifecycle">Managing the Lifecycle of a Service</a>
|
||||
<ol>
|
||||
<li><a href="#LifecycleCallbacks">Implementing the lifecycle callbacks</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h2>Key classes</h2>
|
||||
<ol>
|
||||
<li>{@link android.app.Service}</li>
|
||||
<li>{@link android.app.IntentService}</li>
|
||||
</ol>
|
||||
|
||||
<h2>Samples</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code
|
||||
ServiceStartArguments}</a></li>
|
||||
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
|
||||
LocalService}</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>See also</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a></li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>A service can essentially take two forms:</p>
|
||||
|
||||
<dl>
|
||||
<dt>Started</dt>
|
||||
<dd>A service is "started" when an application component (such as an activity) starts it by
|
||||
calling {@link android.content.Context#startService startService()}. Once started, a service
|
||||
can 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, the
|
||||
service should stop itself.</dd>
|
||||
<dt>Bound</dt>
|
||||
<dd>A service is "bound" when an application component binds to it by calling {@link
|
||||
android.content.Context#bindService bindService()}. A bound service offers a client-server
|
||||
interface that allows components to interact with the service, send requests, get results, and even
|
||||
do so across processes with interprocess communication (IPC). A bound service runs only as long as
|
||||
another 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.</dd>
|
||||
</dl>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 <a href="#Declaring">Declaring the service in the
|
||||
manifest</a>.</p>
|
||||
|
||||
<p class="caution"><strong>Caution:</strong> A service runs in the
|
||||
main thread of its hosting process—the service does <strong>not</strong> create its own thread
|
||||
and does <strong>not</strong> 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.</p>
|
||||
|
||||
|
||||
<h2 id="Basics">The Basics</h2>
|
||||
|
||||
<div class="sidebox-wrapper">
|
||||
<div class="sidebox">
|
||||
<h3>Should you use a service or a thread?</h3>
|
||||
<p>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.</p>
|
||||
<p>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 <a
|
||||
href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html#Threads">Processes and
|
||||
Threading</a> document for more information about threads.</p>
|
||||
<p>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.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<dl>
|
||||
<dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
|
||||
<dd>The system calls this method when another component, such as an activity,
|
||||
requests that the service be started, by calling {@link android.content.Context#startService
|
||||
startService()}. Once this method executes, the service is started and can run in the
|
||||
background indefinitely. If you implement this, it is your responsibility to stop the service when
|
||||
its work is done, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||
android.content.Context#stopService stopService()}. (If you only want to provide binding, you don't
|
||||
need to implement this method.)</dd>
|
||||
<dt>{@link android.app.Service#onBind onBind()}</dt>
|
||||
<dd>The system calls this method when another component wants to bind with the
|
||||
service (such as to perform RPC), by calling {@link android.content.Context#bindService
|
||||
bindService()}. In your implementation of this method, you must provide an interface that clients
|
||||
use to communicate with the service, by returning an {@link android.os.IBinder}. You must always
|
||||
implement this method, but if you don't want to allow binding, then you should return null.</dd>
|
||||
<dt>{@link android.app.Service#onCreate()}</dt>
|
||||
<dd>The system calls this method when the service is first created, to perform one-time setup
|
||||
procedures (before it calls either {@link android.app.Service#onStartCommand onStartCommand()} or
|
||||
{@link android.app.Service#onBind onBind()}). If the service is already running, this method is not
|
||||
called.</dd>
|
||||
<dt>{@link android.app.Service#onDestroy()}</dt>
|
||||
<dd>The system calls this method when the service is no longer used and is being destroyed.
|
||||
Your service should implement this to clean up any resources such as threads, registered
|
||||
listeners, receivers, etc. This is the last call the service receives.</dd>
|
||||
</dl>
|
||||
|
||||
<p>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()}.</p>
|
||||
|
||||
<p>If a component calls
|
||||
{@link android.content.Context#bindService bindService()} to create the service (and {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} is <em>not</em> 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.</p>
|
||||
|
||||
<p>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 <a
|
||||
href="#Foreground">run in the foreground</a> (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 <a
|
||||
href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html">Processes and Threading</a>
|
||||
document.</p>
|
||||
|
||||
<p>In the following sections, you'll see how you can create each type of service and how to use
|
||||
it from other application components.</p>
|
||||
|
||||
|
||||
|
||||
<h3 id="Declaring">Declaring a service in the manifest</h3>
|
||||
|
||||
<p>Like activities (and other components), you must declare all services in your application's
|
||||
manifest file.</p>
|
||||
|
||||
<p>To decalare your service, add a <a
|
||||
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element
|
||||
as a child of the <a
|
||||
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
||||
element. For example:</p>
|
||||
|
||||
<pre>
|
||||
<manifest ... >
|
||||
...
|
||||
<application ... >
|
||||
<service android:name=".ExampleService" />
|
||||
...
|
||||
</application>
|
||||
</manifest>
|
||||
</pre>
|
||||
|
||||
<p>There are other attributes you can include in the <a
|
||||
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element to
|
||||
define properties such as permissions required to start the service and the process in
|
||||
which the service should run. See the <a
|
||||
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element
|
||||
reference for more information.</p>
|
||||
|
||||
<p>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()}.</p>
|
||||
|
||||
<p>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 <a href="#StartingAService">starting a service</a> is discussed below.</p>
|
||||
|
||||
<p>Additionally, you can ensure that your service is private to your application only if
|
||||
you include the <a
|
||||
href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
|
||||
attribute and set it to {@code "false"}. This is effective even if your service supplies intent
|
||||
filters.</p>
|
||||
|
||||
<p>For more information about creating intent filters for your service, see the <a
|
||||
href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
|
||||
document.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="CreatingStartedService">Creating a Started Service</h2>
|
||||
|
||||
<div class="sidebox-wrapper">
|
||||
<div class="sidebox">
|
||||
<h2>Targeting Android 1.6 or lower</h2>
|
||||
<p>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()}).</p>
|
||||
<p>For more information about providing compatibility with versions of Android older than 2.0, see
|
||||
the {@link android.app.Service#onStartCommand onStartCommand()} documentation.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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()}.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p class="caution"><strong>Caution:</strong> 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.</p>
|
||||
|
||||
<p>Traditionally, there are two classes you can extend to create a started service:</p>
|
||||
<dl>
|
||||
<dt>{@link android.app.Service}</dt>
|
||||
<dd>This is the base class for all services. When you extend this class, it's important that
|
||||
you create a new thread in which to do all the service's work, because the service uses your
|
||||
application's main thread, by default, which could slow the performance of any activity your
|
||||
application is running.</dd>
|
||||
<dt>{@link android.app.IntentService}</dt>
|
||||
<dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all
|
||||
start requests, one at a time. This is the best option if you don't require that your service
|
||||
handle multiple requests simultaneously. All you need to do is implement {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()}, which receives the intent for each
|
||||
start request so you can do the background work.</dd>
|
||||
</dl>
|
||||
|
||||
<p>The following sections describe how you can implement your service using either one for these
|
||||
classes.</p>
|
||||
|
||||
|
||||
<h3 id="ExtendingIntentService">Extending the IntentService class</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>The {@link android.app.IntentService} does the following:</p>
|
||||
|
||||
<ul>
|
||||
<li>Creates a default worker thread that executes all intents delivered to {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} separate from your application's main
|
||||
thread.</li>
|
||||
<li>Creates a work queue that passes one intent at a time to your {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()} implementation, so you never have to
|
||||
worry about multi-threading.</li>
|
||||
<li>Stops the service after all start requests have been handled, so you never have to call
|
||||
{@link android.app.Service#stopSelf}.</li>
|
||||
<li>Provides default implementation of {@link android.app.IntentService#onBind onBind()} that
|
||||
returns null.</li>
|
||||
<li>Provides a default implementation of {@link android.app.IntentService#onStartCommand
|
||||
onStartCommand()} that sends the intent to the work queue and then to your {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()} implementation.</li>
|
||||
</ul>
|
||||
|
||||
<p>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.)</p>
|
||||
|
||||
<p>Here's an example implementation of {@link android.app.IntentService}:</p>
|
||||
|
||||
<pre>
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>That's all you need: a constructor and an implementation of {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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()}):</p>
|
||||
|
||||
<pre>
|
||||
@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);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
|
||||
<h3 id="ExtendingService">Extending the Service class</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<pre>
|
||||
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();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>As you can see, it's a lot more work than using {@link android.app.IntentService}.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<dl>
|
||||
<dt>{@link android.app.Service#START_NOT_STICKY}</dt>
|
||||
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
||||
onStartCommand()} returns, <em>do not</em> recreate the service, unless there are pending
|
||||
intents to deliver. This is the safest option to avoid running your service when not necessary
|
||||
and when your application can simply restart any unfinished jobs.</dd>
|
||||
<dt>{@link android.app.Service#START_STICKY}</dt>
|
||||
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
||||
onStartCommand()} returns, recreate the service and call {@link
|
||||
android.app.Service#onStartCommand onStartCommand()}, but <em>do not</em> redeliver the last intent.
|
||||
Instead, the system calls {@link android.app.Service#onStartCommand onStartCommand()} with a
|
||||
null intent, unless there were pending intents to start the service, in which case,
|
||||
those intents are delivered. This is suitable for media players (or similar services) that are not
|
||||
executing commands, but running indefinitely and waiting for a job.</dd>
|
||||
<dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
|
||||
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
||||
onStartCommand()} returns, recreate the service and call {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} with the last intent that was delivered to the
|
||||
service. Any pending intents are delivered in turn. This is suitable for services that are
|
||||
actively performing a job that should be immediately resumed, such as downloading a file.</dd>
|
||||
</dl>
|
||||
<p>For more details about these return values, see the linked reference documentation for each
|
||||
constant.</p>
|
||||
|
||||
|
||||
|
||||
<h3 id="StartingAService">Starting a Service</h3>
|
||||
|
||||
<p>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.)</p>
|
||||
|
||||
<p>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()}:</p>
|
||||
|
||||
<pre>
|
||||
Intent intent = new Intent(this, HelloService.class);
|
||||
startService(intent);
|
||||
</pre>
|
||||
|
||||
<p>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()}.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
|
||||
<h3 id="Stopping">Stopping a service</h3>
|
||||
|
||||
<p>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()}.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 <code>startId</code>
|
||||
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.</p>
|
||||
|
||||
<p class="caution"><strong>Caution:</strong> 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()}.</p>
|
||||
|
||||
<p>For more information about the lifecycle of a service, see the section below about <a
|
||||
href="#Lifecycle">Managing the Lifecycle of a Service</a>.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="CreatingBoundService">Creating a Bound Service</h2>
|
||||
|
||||
<p>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 <em>start</em> it by calling {@link
|
||||
android.content.Context#startService startService()}).</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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 <em>not</em> need to stop a bound service in the way you must when the service is started
|
||||
through {@link android.app.Service#onStartCommand onStartCommand()}).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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 <a
|
||||
href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a>.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="Notifications">Sending Notifications to the User</h2>
|
||||
|
||||
<p>Once running, a service can notify the user of events using <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>See the <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
|
||||
developer guides for more information.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="Foreground">Running a Service in the Foreground</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<pre>
|
||||
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);
|
||||
</pre>
|
||||
|
||||
|
||||
<p>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 <em>not</em> stop the
|
||||
service. However, if you stop the service while it's still running in the foreground, then the
|
||||
notification is also removed.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> 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.</p>
|
||||
|
||||
<p>For more information about notifications, see <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status Bar
|
||||
Notifications</a>.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="Lifecycle">Managing the Lifecycle of a Service</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>The service lifecycle—from when it's created to when it's destroyed—can follow two
|
||||
different paths:</p>
|
||||
|
||||
<ul>
|
||||
<li>A started service
|
||||
<p>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..</p></li>
|
||||
|
||||
<li>A bound service
|
||||
<p>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 <em>not</em> need to stop itself.)</p></li>
|
||||
</ul>
|
||||
|
||||
<p>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. </p>
|
||||
|
||||
|
||||
<h3 id="LifecycleCallbacks">Implementing the lifecycle callbacks</h3>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
|
||||
<div class="figure" style="width:432px">
|
||||
<img src="{@docRoot}images/service_lifecycle.png" alt="" />
|
||||
<p class="img-caption"><strong>Figure 2.</strong> 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()}.</p>
|
||||
</div>
|
||||
|
||||
<pre>
|
||||
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 <em>mStartMode</em>;
|
||||
}
|
||||
@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 <em>mBinder</em>;
|
||||
}
|
||||
@Override
|
||||
public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
|
||||
// All clients have unbound with {@link android.content.Context#unbindService unbindService()}
|
||||
return <em>mAllowRebind</em>;
|
||||
}
|
||||
@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
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Note:</strong> Unlike the activity lifecycle callback methods, you are
|
||||
<em>not</em> required to call the superclass implementation of these callback methods.</p>
|
||||
|
||||
<p>By implementing these methods, you can monitor two nested loops of the service's lifecycle: </p>
|
||||
|
||||
<ul>
|
||||
<li>The <strong>entire lifetime</strong> of a service happens between the time {@link
|
||||
android.app.Service#onCreate onCreate()} is called and the time {@link
|
||||
android.app.Service#onDestroy} returns. Like an activity, a service does its initial setup in
|
||||
{@link android.app.Service#onCreate onCreate()} and releases all remaining resources in {@link
|
||||
android.app.Service#onDestroy onDestroy()}. For example, a
|
||||
music playback service could create the thread where the music will be played in {@link
|
||||
android.app.Service#onCreate onCreate()}, then stop the thread in {@link
|
||||
android.app.Service#onDestroy onDestroy()}.
|
||||
|
||||
<p>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()}.</p></li>
|
||||
|
||||
<li>The <strong>active lifetime</strong> of a service begins with a call to either {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} or {@link android.app.Service#onBind onBind()}.
|
||||
Each method is handed the {@link
|
||||
android.content.Intent} that was passed to either {@link android.content.Context#startService
|
||||
startService()} or {@link android.content.Context#bindService bindService()}, respectively.
|
||||
<p>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.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p class="note"><strong>Note:</strong> 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.</p>
|
||||
|
||||
<p>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()}).</p>
|
||||
|
||||
<p>For more information about creating a service that provides binding, see the <a
|
||||
href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a> document,
|
||||
which includes more information about the {@link android.app.Service#onRebind onRebind()}
|
||||
callback method in the section about <a
|
||||
href="{@docRoot}guide/topics/fundamentals/bound-services.html#Lifecycle">Managing the Lifecycle of
|
||||
a Bound Service</a>.</p>
|
||||
|
||||
|
||||
|
||||
<h2>Beginner's Path</h2>
|
||||
|
||||
<p>To learn how to query data from the system or other applications (such as contacts or media
|
||||
stored on the device), continue with the <b><a
|
||||
href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b>
|
||||
document.</p>
|
||||
BIN
docs/html/images/fundamentals/service_binding_tree_lifecycle.png
Normal file
BIN
docs/html/images/fundamentals/service_binding_tree_lifecycle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 74 KiB |
Reference in New Issue
Block a user