From e40c4636d970c50f7719e7d5067963be93c25750 Mon Sep 17 00:00:00 2001 From: Scott Main Date: Mon, 25 Jun 2012 10:02:13 -0700 Subject: docs: move AIDL doc under Services in api guides. Change-Id: I525de97958e2093af15cce2b007ec022cb315a71 --- docs/html/guide/components/aidl.jd | 465 +++++++++++++++++++++ docs/html/guide/components/bound-services.jd | 4 +- .../guide/google/play/billing/billing_overview.jd | 2 +- docs/html/guide/guide_toc.cs | 3 + docs/html/intl/ja/guide/topics/fundamentals.jd | 4 +- docs/html/sitemap.txt | 2 +- docs/html/tools/aidl.jd | 465 --------------------- docs/html/tools/help/index.jd | 2 +- 8 files changed, 475 insertions(+), 472 deletions(-) create mode 100644 docs/html/guide/components/aidl.jd delete mode 100644 docs/html/tools/aidl.jd diff --git a/docs/html/guide/components/aidl.jd b/docs/html/guide/components/aidl.jd new file mode 100644 index 0000000..805b7ec --- /dev/null +++ b/docs/html/guide/components/aidl.jd @@ -0,0 +1,465 @@ +page.title=Android Interface Definition Language (AIDL) +@jd:body + + +
+ +
+ + +

AIDL (Android Interface Definition Language) is similar to other IDLs you might have +worked with. It allows you to define the programming interface that both +the client and service agree upon in order to communicate with each other using +interprocess communication (IPC). On Android, one process cannot 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 objects across that boundary for you. The code to +do that marshalling is tedious to write, so Android handles it for you with AIDL.

+ +

Note: Using AIDL is necessary only if you allow clients from +different applications to access your service for IPC and want to handle multithreading in your +service. If you do not need to perform concurrent IPC across +different applications, you should create your interface by implementing a +Binder or, if you want to perform IPC, but do not need to handle multithreading, +implement your interface using a Messenger. +Regardless, be sure that you understand Bound Services before +implementing an AIDL.

+ +

Before you begin designing your AIDL interface, be aware that calls to an AIDL interface are +direct function calls. You should not make assumptions about the thread in which the call +occurs. What happens is different depending on whether the call is from a thread in the +local process or a remote process. Specifically:

+ + + + +

Defining an AIDL Interface

+ +

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 binds to the service.

+ +

When you build each application that contains the {@code .aidl} file, the Android SDK tools +generate an {@link android.os.IBinder} interface based on the {@code .aidl} file and save it in +the project's {@code gen/} directory. The service must implement the {@link android.os.IBinder} +interface as appropriate. The client applications can then bind to the service and call methods from +the {@link android.os.IBinder} to perform IPC.

+ +

To create a bounded service using AIDL, follow these steps:

+
    +
  1. Create the .aidl file +

    This file defines the programming interface with method signatures.

    +
  2. +
  3. Implement the interface +

    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.

    +
  4. +
  5. Expose the interface to clients +

    Implement a {@link android.app.Service Service} and override {@link +android.app.Service#onBind onBind()} to return your implementation of the {@code Stub} +class.

    +
  6. +
+ +

Caution: Any changes that you make to your AIDL interface after +your first release must remain backward compatible in order to avoid breaking other applications +that use your service. That is, because your {@code .aidl} file must be copied to other applications +in order for them to access your service's interface, you must maintain support for the original +interface.

+ + +

1. Create the .aidl file

+ +

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.

+ +

You must construct the {@code .aidl} file using the Java programming language. Each {@code .aidl} +file must define a single interface and requires only the interface declaration and method +signatures.

+ +

By default, AIDL supports the following data types:

+ + + +

You must include an {@code import} statement for each additional type not listed above, even if +they are defined in the same package as your interface.

+ +

When defining your service interface, be aware that:

+ + +

Here is an example {@code .aidl} file:

+ +
+// IRemoteService.aidl
+package com.example.android;
+
+// Declare any non-default types here with import statements
+
+/** Example service interface */
+interface IRemoteService {
+    /** Request the process ID of this service, to do evil things with it. */
+    int getPid();
+
+    /** Demonstrates some basic types that you can use as parameters
+     * and return values in AIDL.
+     */
+    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
+            double aDouble, String aString);
+}
+
+ +

Simply save your {@code .aidl} file in your project's {@code src/} directory and when you +build your application, the SDK tools generate the {@link android.os.IBinder} interface file in your +project's {@code gen/} directory. The generated file name matches the {@code .aidl} file name, but +with a {@code .java} extension (for example, {@code IRemoteService.aidl} results in {@code +IRemoteService.java}).

+ +

If you use Eclipse, the incremental build generates the binder class almost immediately. If you +do not use Eclipse, then the Ant tool generates the binder class next time you build your +application—you should build your project with ant debug (or ant +release) as soon as you're finished writing the {@code .aidl} file, so that your code can +link against the generated class.

+ + +

2. Implement the interface

+ +

When you build your application, the Android SDK tools generate a {@code .java} interface file +named after your {@code .aidl} file. The generated interface includes a subclass named {@code Stub} +that is an abstract implementation of its parent interface (for example, {@code +YourInterface.Stub}) and declares all the methods from the {@code .aidl} file.

+ +

Note: {@code Stub} also +defines a few helper methods, most notably {@code asInterface()}, which takes an {@link +android.os.IBinder} (usually the one passed to a client's {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method) and +returns an instance of the stub interface. See the section Calling an IPC +Method for more details on how to make this cast.

+ +

To implement the interface generated from the {@code .aidl}, extend the generated {@link +android.os.Binder} interface (for example, {@code YourInterface.Stub}) and implement the methods +inherited from the {@code .aidl} file.

+ +

Here is an example implementation of an interface called {@code IRemoteService} (defined by the +{@code IRemoteService.aidl} example, above) using an anonymous instance:

+ +
+private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+    public int getPid(){
+        return Process.myPid();
+    }
+    public void basicTypes(int anInt, long aLong, boolean aBoolean,
+        float aFloat, double aDouble, String aString) {
+        // Does nothing
+    }
+};
+
+ +

Now the {@code mBinder} is an instance of the {@code Stub} class (a {@link android.os.Binder}), +which defines the RPC interface for the service. In the next step, this instance is exposed to +clients so they can interact with the service.

+ +

There are a few rules you should be aware of when implementing your AIDL interface:

+ + + +

3. Expose the interface to clients

+ +

Once you've implemented the interface for your service, you need to expose it to +clients so they can bind to it. To expose the interface +for your service, extend {@link android.app.Service Service} and implement {@link +android.app.Service#onBind onBind()} to return an instance of your class that implements +the generated {@code Stub} (as discussed in the previous section). Here's an example +service that exposes the {@code IRemoteService} example interface to clients.

+ +
+public class RemoteService extends Service {
+    @Override
+    public void onCreate() {
+        super.onCreate();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        // Return the interface
+        return mBinder;
+    }
+
+    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+        public int getPid(){
+            return Process.myPid();
+        }
+        public void basicTypes(int anInt, long aLong, boolean aBoolean,
+            float aFloat, double aDouble, String aString) {
+            // Does nothing
+        }
+    };
+}
+
+ +

Now, when a client (such as an activity) calls {@link android.content.Context#bindService +bindService()} to connect to this service, the client's {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback receives the +{@code mBinder} instance returned by the service's {@link android.app.Service#onBind onBind()} +method.

+ +

The client must also have access to the interface class, so if the client and service are in +separate applications, then the client's application must have a copy of the {@code .aidl} file +in its {@code src/} directory (which generates the {@code android.os.Binder} +interface—providing the client access to the AIDL methods).

+ +

When the client receives the {@link android.os.IBinder} in the {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback, it must call +YourServiceInterface.Stub.asInterface(service) to cast the returned +parameter to YourServiceInterface type. For example:

+ +
+IRemoteService mIRemoteService;
+private ServiceConnection mConnection = new ServiceConnection() {
+    // Called when the connection with the service is established
+    public void onServiceConnected(ComponentName className, IBinder service) {
+        // Following the example above for an AIDL interface,
+        // this gets an instance of the IRemoteInterface, which we can use to call on the service
+        mIRemoteService = IRemoteService.Stub.asInterface(service);
+    }
+
+    // Called when the connection with the service disconnects unexpectedly
+    public void onServiceDisconnected(ComponentName className) {
+        Log.e(TAG, "Service has unexpectedly disconnected");
+        mIRemoteService = null;
+    }
+};
+
+ +

For more sample code, see the {@code +RemoteService.java} class in ApiDemos.

+ + + + + + + + +

Passing Objects over IPC

+ +

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 channel and your class must support the {@link +android.os.Parcelable} interface. Supporting the {@link android.os.Parcelable} interface is +important because it allows the Android system to decompose objects into primitives that can be +marshalled across processes.

+ +

To create a class that supports the {@link android.os.Parcelable} protocol, you must do the +following: +

    +
  1. Make your class implement the {@link android.os.Parcelable} interface.
  2. +
  3. Implement {@link android.os.Parcelable#writeToParcel writeToParcel}, which takes the +current state of the object and writes it to a {@link android.os.Parcel}.
  4. +
  5. Add a static field called CREATOR to your class which is an object implementing +the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.
  6. +
  7. Finally, create an {@code .aidl} file that declares your parcelable class (as shown for the +{@code Rect.aidl} file, below). +

    If you are using a custom build process, do not add the {@code .aidl} file to your +build. Similar to a header file in the C language, this {@code .aidl} file isn't compiled.

  8. +
+ +

AIDL uses these methods and fields in the code it generates to marshall and unmarshall +your objects.

+ +

For example, here is a {@code Rect.aidl} file to create a {@code Rect} class that's +parcelable:

+ +
+package android.graphics;
+
+// Declare Rect so AIDL can find it and knows that it implements
+// the parcelable protocol.
+parcelable Rect;
+
+ +

And here is an example of how the {@link android.graphics.Rect} class implements the +{@link android.os.Parcelable} protocol.

+ +
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public final class Rect implements Parcelable {
+    public int left;
+    public int top;
+    public int right;
+    public int bottom;
+
+    public static final Parcelable.Creator<Rect> CREATOR = new
+Parcelable.Creator<Rect>() {
+        public Rect createFromParcel(Parcel in) {
+            return new Rect(in);
+        }
+
+        public Rect[] newArray(int size) {
+            return new Rect[size];
+        }
+    };
+
+    public Rect() {
+    }
+
+    private Rect(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public void writeToParcel(Parcel out) {
+        out.writeInt(left);
+        out.writeInt(top);
+        out.writeInt(right);
+        out.writeInt(bottom);
+    }
+
+    public void readFromParcel(Parcel in) {
+        left = in.readInt();
+        top = in.readInt();
+        right = in.readInt();
+        bottom = in.readInt();
+    }
+}
+
+ +

The marshalling in the {@code Rect} class is pretty simple. Take a look at the other +methods on {@link android.os.Parcel} to see the other kinds of values you can write +to a Parcel.

+ +

Warning: Don't forget the security implications of receiving +data from other processes. In this case, the {@code Rect} reads four numbers from the {@link +android.os.Parcel}, but it is up to you to ensure that these are within the acceptable range of +values for whatever the caller is trying to do. See Security and Permissions for more +information about how to keep your application secure from malware.

+ + + +

Calling an IPC Method

+ +

Here are the steps a calling class must take to call a remote interface defined with AIDL:

+
    +
  1. Include the {@code .aidl} file in the project {@code src/} directory.
  2. +
  3. Declare an instance of the {@link android.os.IBinder} interface (generated based on the +AIDL).
  4. +
  5. Implement {@link android.content.ServiceConnection ServiceConnection}.
  6. +
  7. Call {@link +android.content.Context#bindService(android.content.Intent,android.content.ServiceConnection,int) + Context.bindService()}, passing in your {@link +android.content.ServiceConnection} implementation.
  8. +
  9. In your implementation of {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()}, +you will receive an {@link android.os.IBinder} instance (called service). Call +YourInterfaceName.Stub.asInterface((IBinder)service) to + cast the returned parameter to YourInterface type.
  10. +
  11. Call the methods that you defined on your interface. You should always trap + {@link android.os.DeadObjectException} exceptions, which are thrown when + the connection has broken; this will be the only exception thrown by remote + methods.
  12. +
  13. To disconnect, call {@link +android.content.Context#unbindService(android.content.ServiceConnection) + Context.unbindService()} with the instance of your interface.
  14. +
+

A few comments on calling an IPC service:

+ + +

For more information about binding to a service, read the Bound Services +document.

+ +

Here is some sample code demonstrating calling an AIDL-created service, taken + from the Remote Service sample in the ApiDemos project.

+

{@sample development/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java + calling_a_service}

diff --git a/docs/html/guide/components/bound-services.jd b/docs/html/guide/components/bound-services.jd index b6a2512..43e6e5e 100644 --- a/docs/html/guide/components/bound-services.jd +++ b/docs/html/guide/components/bound-services.jd @@ -170,7 +170,7 @@ can then extend within your service.

create a bound service, because it may require multithreading capabilities and can result in a more complicated implementation. As such, AIDL is not suitable for most applications and this document does not discuss how to use it for your service. If you're certain that you need -to use AIDL directly, see the AIDL +to use AIDL directly, see the AIDL document.

@@ -341,7 +341,7 @@ service, which must then handle multi-threading.

For most applications, the service doesn't need to perform multi-threading, so using a {@link android.os.Messenger} allows the service to handle one call at a time. If it's important that your service be multi-threaded, then you should use AIDL to define your interface.

+href="{@docRoot}guide/components/aidl.html">AIDL to define your interface.

diff --git a/docs/html/guide/google/play/billing/billing_overview.jd b/docs/html/guide/google/play/billing/billing_overview.jd index d6725bb..05139b4 100755 --- a/docs/html/guide/google/play/billing/billing_overview.jd +++ b/docs/html/guide/google/play/billing/billing_overview.jd @@ -154,7 +154,7 @@ messaging that takes place between your application and the Google Play applicat

Your application sends in-app billing requests by invoking a single IPC method (sendBillingRequest()), which is exposed by the MarketBillingService interface. This interface is defined in an Android Interface Definition Language file +href="{@docRoot}guide/components/aidl.html">Android Interface Definition Language file (IMarketBillingService.aidl). You can download this AIDL file with the in-app billing sample application.

diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 44b977e..fee1f35 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -41,6 +41,9 @@
  • Bound Services
  • +
  • + AIDL +