diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-02-16 18:01:18 -0800 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2010-02-18 16:28:23 -0800 |
commit | 75288fa1a4ee4886959af7243995d8afd9c3c905 (patch) | |
tree | 74df80d463faa201b2c00fb1d83ed776b406fe41 /core | |
parent | 9599452dd9c001cc2217175227514ef9ac631cd9 (diff) | |
download | frameworks_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')
-rw-r--r-- | core/java/android/app/Service.java | 60 | ||||
-rw-r--r-- | core/java/android/os/Message.java | 76 |
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); |