一、Create the .aidl file
AIDL uses a simple syntaxthat lets youdeclarean interfacewith one or more methods that can take parameters and return values.The parametersandreturn values can be of any type,
29
even otherAIDL-generated interfaces.
You must construct the .aidl file using the Java programming language. Each .aidl filemust definea singleinterface and requires only theinterfacedeclaration andmethod signatures.
By default, AIDLsupports the followingdatatypes:
All primitive types in theJava programminglanguage (suchas int, long, char, boolean, and so on)
String
CharSequence
List
All elements inthe List must beoneofthesupporteddata types inthis list or one of the other AIDL-generated interfacesor parcelables you'vedeclared.A List may optionally be used as a "generic" class (for example, List<String>). The actual concrete class that the other side receives is always an ArrayList, although the method is generated to use the List interface.
Map
All elements inthe Mapmustbe one of the supported data typesin this list oroneof the other AIDL-generated interfaces or parcelables you've declared.Generic maps, (such as those of the formMap<String,Integer> are notsupported. The actualconcrete class that the other side receivesis always a HashMap,although the method is generated to use theMap interface.
You must includean importstatement for each additionaltypenotlisted above,evenif they are defined in thesamepackageas yourinterface.
When definingyourserviceinterface, beaware that:
Methods cantakezeroor more parameters, andreturn avalue orvoid.
All non-primitive parameters require adirectional tagindicating which way the data goes. Eitherin,out,orinout (see the example below).
Primitivesare in by default, and cannotbe otherwise.
Caution: You should limit the direction to what is truly needed, because marshalling parametersisexpensive.
All code comments included in the .aidl fileare included in the generated IBinder interface (except for commentsbefore theimport and packagestatements).
Only methods aresupported; youcannot exposestatic fields inAIDL.
Here is anexample.aidl file: // IRemoteService.aidl package com.example.android;
30
// Declareany non-defaulttypes here with importstatements
/** Example service interface */ interface IRemoteService {
/** RequesttheprocessIDof thisservice, to doevilthings with it. */ int getPid();
/** Demonstratessomebasic types that you can useas parameters *andreturn values in AIDL.
Simply save your .aidl file in your project's src/ directory and when you build your application, the SDK tools generate the IBinder interface file in your project's gen/ directory. The generated file name matches the .aidl file name, but with a .java extension (for example, IRemoteService.aidl results in 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 .aidl file, so that your code can link against the generated class.
二、Implement the interface
When you build yourapplication, the Android SDKtools generate a.java interfacefile named after your .aidl file. The generatedinterfaceincludes a subclass named Stub that is an abstract implementation of its parent interface (for example, YourInterface.Stub) and declares all themethods from the .aidlfile.
To implement the interface generated fromthe .aidl,extend the generatedBinder interface (for example, YourInterface.Stub) and implement the methods inherited from the .aidl file.
Here is anexample implementation of an interface calledIRemoteService(defined bythe IRemoteService.aidl example,above) using ananonymousinstance:
private finalIRemoteService.Stub mBinder = new IRemoteService.Stub() { public intgetPid(){
returnProcess.myPid();
}
public voidbasicTypes(intanInt, long aLong,boolean aBoolean, float aFloat,double aDouble, String aString){
// Does nothing
}
};
31
Now the mBinder is an instance ofthe Stub class (a Binder), which defines the RPC interface for the service. In the next step, thisinstance isexposed to clients so they can interact with the service.
There are a fewrulesyou should be aware ofwhenimplementingyourAIDLinterface:
Incoming calls are not guaranteedto be executed on the main thread, so you need to think about multithreading from the start and properlybuild yourservice tobe thread-safe.
By default,RPCcalls are synchronous. If you knowthat the servicetakes more than a few milliseconds to complete a request, you should not callit from the activity's main thread, becauseitmighthangtheapplication(Android mightdisplayan "Application is
Not Responding" dialog)—you should usually callthem from a separate thread in the client.
No exceptionsthatyou throw are sent back tothecaller.
三、Expose the interface to clients
Once you've implemented the interface for your service, you need toexpose it to clients so they can bind toit.To expose the interface foryour service, extend Service and implement onBind() to return an instance of your class that implements the generated Stub (as discussed in the previous section). Here's an example service that exposesthe IRemoteService example interface to clients.
publicclass RemoteServiceextends Service { @Override
public voidonCreate() { super.onCreate();
}
@Override
public IBinder onBind(Intentintent) { // Return theinterface
returnmBinder;
}
private finalIRemoteService.Stub mBinder = new IRemoteService.Stub() { publicintgetPid(){
returnProcess.myPid();
}
publicvoidbasicTypes(intanInt, long aLong,boolean aBoolean, floataFloat,double aDouble,String aString){
// Does nothing
}
};
32
}
Now, when a client(suchas an activity) callsbindService()to connect tothisservice,the client's onServiceConnected() callback receives the mBinder instance returned by the service's onBind() method.
The client mustalso have access to theinterface class,so if the clientandservice are in separate applications,thenthe client's application must have a copy of the .aidl file in
its src/ directory (which generatesthe android.os.Binder interface—providingthe client accessto theAIDLmethods).
When the clientreceives the IBinder in the onServiceConnected() callback, it must call YourServiceInterface.Stub.asInterface(service) to cast the returned parameter to YourServiceInterfacetype.For example:
IRemoteService mIRemoteService;
private ServiceConnection mConnection =new ServiceConnection(){ // Called when theconnection withthe service isestablished
public voidonServiceConnected(ComponentNameclassName,IBinderservice) {
//Following theexample aboveforan AIDL interface,
//this gets an instance of the IRemoteInterface, which we canuse to call on the service mIRemoteService= IRemoteService.Stub.asInterface(service);
}
// Called when theconnection withthe service disconnectsunexpectedly public voidonServiceDisconnected(ComponentName className){
Log.e(TAG,"Service hasunexpectedly disconnected"); mIRemoteService= null;