summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2010-02-16 18:01:18 -0800
committerDianne Hackborn <hackbod@google.com>2010-02-18 16:28:23 -0800
commit75288fa1a4ee4886959af7243995d8afd9c3c905 (patch)
tree74df80d463faa201b2c00fb1d83ed776b406fe41 /core/java
parent9599452dd9c001cc2217175227514ef9ac631cd9 (diff)
downloadframeworks_base-75288fa1a4ee4886959af7243995d8afd9c3c905.zip
frameworks_base-75288fa1a4ee4886959af7243995d8afd9c3c905.tar.gz
frameworks_base-75288fa1a4ee4886959af7243995d8afd9c3c905.tar.bz2
Improve Service documentation with some samples.
Also some small tweaks to the Message API to improve its use in the MessengerService sample.
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Service.java60
-rw-r--r--core/java/android/os/Message.java76
2 files changed, 121 insertions, 15 deletions
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 8ec5bd4..6767332 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -56,6 +56,8 @@ import java.io.PrintWriter;
* <li><a href="#ServiceLifecycle">Service Lifecycle</a>
* <li><a href="#Permissions">Permissions</a>
* <li><a href="#ProcessLifecycle">Process Lifecycle</a>
+ * <li><a href="#LocalServiceSample">Local Service Sample</a>
+ * <li><a href="#RemoteMessengerServiceSample">Remote Messenger Service Sample</a>
* </ol>
*
* <a name="ServiceLifecycle"></a>
@@ -166,6 +168,64 @@ import java.io.PrintWriter;
* (such as an {@link android.app.Activity}) can, of course, increase the
* importance of the overall
* process beyond just the importance of the service itself.
+ *
+ * <a name="LocalServiceSample"></a>
+ * <h3>Local Service Sample</h3>
+ *
+ * <p>One of the most common uses of a Service is as a secondary component
+ * running alongside other parts of an application, in the same process as
+ * the rest of the components. All components of an .apk run in the same
+ * process unless explicitly stated otherwise, so this is a typical situation.
+ *
+ * <p>When used in this way, by assuming the
+ * components are in the same process, you can greatly simplify the interaction
+ * between them: clients of the service can simply cast the IBinder they
+ * receive from it to a concrete class published by the service.
+ *
+ * <p>An example of this use of a Service is shown here. First is the Service
+ * itself, publishing a custom class when bound:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
+ * service}
+ *
+ * <p>With that done, one can now write client code that directly accesses the
+ * running service, such as:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.java
+ * bind}
+ *
+ * <a name="RemoteMessengerServiceSample"></a>
+ * <h3>Remote Messenger Service Sample</h3>
+ *
+ * <p>If you need to be able to write a Service that can perform complicated
+ * communication with clients in remote processes (beyond simply the use of
+ * {@link Context#startService(Intent) Context.startService} to send
+ * commands to it), then you can use the {@link android.os.Messenger} class
+ * instead of writing full AIDL files.
+ *
+ * <p>An example of a Service that uses Messenger as its client interface
+ * is shown here. First is the Service itself, publishing a Messenger to
+ * an internal Handler when bound:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.java
+ * service}
+ *
+ * <p>If we want to make this service run in a remote process (instead of the
+ * standard one for its .apk), we can use <code>android:process</code> in its
+ * manifest tag to specify one:
+ *
+ * {@sample development/samples/ApiDemos/AndroidManifest.xml remote_service_declaration}
+ *
+ * <p>Note that the name "remote" chosen here is arbitrary, and you can use
+ * other names if you want additional processes. The ':' prefix appends the
+ * name to your package's standard process name.
+ *
+ * <p>With that done, clients can now bind to the service and send messages
+ * to it. Note that this allows clients to register with it to receive
+ * messages back as well:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.java
+ * bind}
*/
public abstract class Service extends ContextWrapper implements ComponentCallbacks {
private static final String TAG = "Service";
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 4130109..476da1d 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -40,20 +40,36 @@ public final class Message implements Parcelable {
*/
public int what;
- // Use these fields instead of using the class's Bundle if you can.
- /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()}
- if you only need to store a few integer values. */
+ /**
+ * arg1 and arg2 are lower-cost alternatives to using
+ * {@link #setData(Bundle) setData()} if you only need to store a
+ * few integer values.
+ */
public int arg1;
- /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()}
- if you only need to store a few integer values.*/
+ /**
+ * arg1 and arg2 are lower-cost alternatives to using
+ * {@link #setData(Bundle) setData()} if you only need to store a
+ * few integer values.
+ */
public int arg2;
- /** An arbitrary object to send to the recipient. This must be null when
- * sending messages across processes. */
+ /**
+ * An arbitrary object to send to the recipient. When using
+ * {@link Messenger} to send the message across processes this can only
+ * be non-null if it contains a Parcelable of a framework class (not one
+ * implemented by the application). For other data transfer use
+ * {@link #setData}.
+ *
+ * <p>Note that Parcelable objects here are not supported prior to
+ * the {@link android.os.Build.VERSION_CODES#FROYO} release.
+ */
public Object obj;
- /** Optional Messenger where replies to this message can be sent.
+ /**
+ * Optional Messenger where replies to this message can be sent. The
+ * semantics of exactly how this is used are up to the sender and
+ * receiver.
*/
public Messenger replyTo;
@@ -278,14 +294,22 @@ public final class Message implements Parcelable {
* the <em>target</em> {@link Handler} that is receiving this Message to
* dispatch it. If
* not set, the message will be dispatched to the receiving Handler's
- * {@link Handler#handleMessage(Message Handler.handleMessage())}. */
+ * {@link Handler#handleMessage(Message Handler.handleMessage())}.
+ */
public Runnable getCallback() {
return callback;
}
/**
* Obtains a Bundle of arbitrary data associated with this
- * event, lazily creating it if necessary. Set this value by calling {@link #setData(Bundle)}.
+ * event, lazily creating it if necessary. Set this value by calling
+ * {@link #setData(Bundle)}. Note that when transferring data across
+ * processes via {@link Messenger}, you will need to set your ClassLoader
+ * on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
+ * Bundle.setClassLoader()} so that it can instantiate your objects when
+ * you retrieve them.
+ * @see #peekData()
+ * @see #setData(Bundle)
*/
public Bundle getData() {
if (data == null) {
@@ -297,14 +321,21 @@ public final class Message implements Parcelable {
/**
* Like getData(), but does not lazily create the Bundle. A null
- * is returned if the Bundle does not already exist.
+ * is returned if the Bundle does not already exist. See
+ * {@link #getData} for further information on this.
+ * @see #getData()
+ * @see #setData(Bundle)
*/
public Bundle peekData() {
return data;
}
- /** Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
- * as a lower cost way to send a few simple integer values, if you can. */
+ /**
+ * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
+ * as a lower cost way to send a few simple integer values, if you can.
+ * @see #getData()
+ * @see #peekData()
+ */
public void setData(Bundle data) {
this.data = data;
}
@@ -381,13 +412,25 @@ public final class Message implements Parcelable {
}
public void writeToParcel(Parcel dest, int flags) {
- if (obj != null || callback != null) {
+ if (callback != null) {
throw new RuntimeException(
- "Can't marshal objects across processes.");
+ "Can't marshal callbacks across processes.");
}
dest.writeInt(what);
dest.writeInt(arg1);
dest.writeInt(arg2);
+ if (obj != null) {
+ try {
+ Parcelable p = (Parcelable)obj;
+ dest.writeInt(1);
+ dest.writeParcelable(p, flags);
+ } catch (ClassCastException e) {
+ throw new RuntimeException(
+ "Can't marshal non-Parcelable objects across processes.");
+ }
+ } else {
+ dest.writeInt(0);
+ }
dest.writeLong(when);
dest.writeBundle(data);
Messenger.writeMessengerOrNullToParcel(replyTo, dest);
@@ -397,6 +440,9 @@ public final class Message implements Parcelable {
what = source.readInt();
arg1 = source.readInt();
arg2 = source.readInt();
+ if (source.readInt() != 0) {
+ obj = source.readParcelable(getClass().getClassLoader());
+ }
when = source.readLong();
data = source.readBundle();
replyTo = Messenger.readMessengerOrNullFromParcel(source);