Develop series-API Guides-application components-Services-AIDL,-api-services-aidl
Android Interface Description Language (AIDL)
AIDL defines the interfaces that clients and servers comply with for inter-process communication.
Note: AIDL Application Scenario: clients from multiple applications access the service through IPC, and the service needs to process multithreading;
If you do not have concurrent scenarios from different clients, we recommend that you use the Binder interface. If you need to process IPC but do not have multiple threads, we recommend that you use Messenger. (These two methods are described at http://www.cnblogs.com/konger/p/3923518.html)
The AIDL interface call is a direct function call method, which is different from that of other processes:
- The same process calls the AIDL interface. The AIDL interface code is completed in the thread that calls this interface. (If the same process only calls AIDL, we recommend using the Binder Interface)
- When other processes call AIDL, they will assign a thread in the thread pool of the AIDL process to execute the AIDL code. Therefore, the AIDL may be accessed by multiple threads at the same time, and thread security must be ensured.
- You can use the oneway keyword to modify the behavior attribute of a remote call. If this keyword is used, the remote call will directly return results without blocking the running of the caller thread. The keyword oneway has no effect on local calls. (Question: if a direct return is returned, there are two problems: 1. How to obtain the result? 2. May background operations be interrupted ?)
Define the AIDL Interface
In the src directory, use Java syntax to define the interface file with the. aidl suffix. both the client and the server need to save a copy of the interface file. During compilation, the SDK generates an IBinder interface for the aild file in the gen directory. The server implements this interface, the client binds the service, and CALLS methods in the interface to implement inter-process communication.
To create an AIDL-implemented server, follow these steps:
Note: Once the aidl file is released, the compatibility between the client and the server must be changed.
1. Create an aidl File
The AIDL interface can define multiple functions that bring parameters and return values. The parameters and return values can be of any type, or even other AIDL interfaces.
By default, AIDL supports the following data types:
- Basic Types of Java (int, long, char, boolean, etc)
- String
- CharSequence
- List
The elements in the list must be of the following three types: Data Types supported by AIDL, Apis generated by other AIDL, and custom serializable types. The actual type received is ArrayList (?)
- Map
The type must be the same as List. Map is not supported. The actual type received is HashMap.
You need to import other types other than the above types, even in the same package.
When defining a service interface, note the following:
- The method can be set to 0 or multiple parameters, and can return specific values or no return values.
- All non-basic types of parameters must specify the parameter direction: input parameter in output parameter out inout, default is in
- All annotations in the aidl file are included in the automatically generated IBinder interface file (unless the annotations are prior to import and package)
- AIDL only supports methods and does not support Variables
Aidl sample code:
// IRemoteService.aidlpackage 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);}
Save your aidl file in the src directory of the Project. When you compile the file, the SDK tool will automatically generate the IBinder interface file under the gen directory. The generated file name is the same as that of the aidl file, the suffix is. java (IRemoteService. aidl corresponds to IRemoteService. java ).
If Eclipse is used, the incremental compilation will immediately generate a java interface file. If you use the Ant tool, you need to use ant debug or ant release for compilation.
2. Implementation Interface
The automatically generated java interface file contains the abstract subclass named Stub (YourInterface. Stub ).
Inherits the Stub class and implements the interfaces in it.
Sample Code:
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 }};
MBinder is a Stub instance and defines a remote call interface for the service. Next, the client calls the service through mBinder.
To implement the AIDL interface, follow these rules:
- Thread security. The call may come from multiple threads.
- By default, RPC is a synchronous call. If the service takes a long time to complete processing, it is not recommended to call it in the main thread of the application; otherwise, ANR may occur.
- The service will not be thrown to the client.
3. Expose the interface to the client
Inherit Service, implement onBind, and return mBinder (Stub class), for example:
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 } };}
When the client calls the bindService to connect to the service, the onServiceConnected callback function of the client will be received by the mBinder instance through the onBind function of the service.
When the client and the server are in different applications, the client needs to copy the aidl file.
The client receives the onServiceConnected callback from IBinder and needs to callYourServiceInterface. Stub. asInterface (service)YourServiceInterface type. 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; }};
Passing objects through IPC
To implement the Parcelable interface for a custom class, follow these steps:
AIDL uses the member serialization and deserialization objects of these methods. The following code demonstrates how to enable the Rect class to support serialization (parcelable)
package android.graphics;// Declare Rect so AIDL can find it and knows that it implements// the parcelable protocol.parcelable Rect;
The following example demonstrates how to implement the Parcelable protocol for the Rect class.
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 = newParcelable.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(); }}
Call the IPC Method
The following describes how to call the remote AIDL interface:
1. Include the. adil file in the src/directory.
2. Declare an instance of the IBinder interface (generated through the. aidl file.
3. Implement ServiceConnection.
4. Call Context. bindService () to bind your ServiceConnection implementation Class Object (Remote Server ).
5. In the onServiceConnected () method, the IBinder object (that is, the server) will be received. Call YourInterfaceName. Stub. asInterface (IBinder) service) to convert the return value to the YourInterface type.
6. Call the methods defined in the interface and always catch the DeadObjectException exception thrown when the connection is interrupted. This is the only exception that may be thrown by the remote method.
7. Call the Context. unbindService () method to disconnect the connection.
Here are a few tips for calling the IPC service:
- Objects are referenced and counted between processes.
- Anonymous objects can be sent as method parameters.