一、什么是AIDL(Android 接口定义语言)
AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似。
您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。
在 Android 上,一个进程通常无法访问另一个进程的内存。
尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。
编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理。
上面这段话是google文档的描述,目的是为了进程间通信,通过aidl文件可以生成java文件,方便实现ipc。底层还是binder通信,可以理解为多了一层包装,方便书写。
二、AIDL文件语法
AIDL 使用简单语法,使您能通过可带参数和返回值的一个或多个方法来声明接口。
参数和返回值可以是任意类型,甚至可以是其他 AIDL 生成的接口。
您必须使用 Java 编程语言构建 .aidl 文件。
每个 .aidl 文件都必须定义单个接口,并且只需包含接口声明和方法签名。
分类:
- 第一类是 Java 编程语言中的基本类型,(如 int、long、char、boolean 等等)
- 第二类包括 String、List、Map 和 CharSequence,
- 第三类是其他 AIDL 生成的 interface,
- 第四类是实现了 Parcelable protocol 的自定义类。
之外ANT生成java文件时还支持Bundle,eclips的ADT不支持,不过得为in类型。
in/out区别:
所有非原语参数都需要指示数据走向的方向标记。
可以是 in、out 或 inout(见以下示例)。
原语默认为 in,不能是其他方向。
举个例子:
/*
* This file is auto-generated. DO NOT MODIFY.
*/
package com.linxtu.demo.api.common.aidl;
// Declare any non-default types here with import statements
public interface IDemoApiManager extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.linxtu.demo.api.common.aidl.IDemoApiManager
{
private static final java.lang.String DESCRIPTOR = "com.linxtu.demo.api.common.aidl.IDemoApiManager";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.linxtu.demo.api.common.aidl.IDemoApiManager interface,
* generating a proxy if needed.
*/
public static com.linxtu.demo.api.common.aidl.IDemoApiManager asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.linxtu.demo.api.common.aidl.IDemoApiManager))) {
return ((com.linxtu.demo.api.common.aidl.IDemoApiManager)iin);
}
return new com.linxtu.demo.api.common.aidl.IDemoApiManager.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_addTest:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.addTest(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_getDemoApiRegister:
{
data.enforceInterface(DESCRIPTOR);
com.linxtu.demo.api.common.aidl.IDemoRegisterAIDL _result = this.getDemoApiRegister();
reply.writeNoException();
reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.linxtu.demo.api.common.aidl.IDemoApiManager
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override public int addTest(int anIntA, int anIntB) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anIntA);
_data.writeInt(anIntB);
mRemote.transact(Stub.TRANSACTION_addTest, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public com.linxtu.demo.api.common.aidl.IDemoRegisterAIDL getDemoApiRegister() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.linxtu.demo.api.common.aidl.IDemoRegisterAIDL _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getDemoApiRegister, _data, _reply, 0);
_reply.readException();
_result = com.linxtu.demo.api.common.aidl.IDemoRegisterAIDL.Stub.asInterface(_reply.readStrongBinder());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_addTest = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getDemoApiRegister = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public int addTest(int anIntA, int anIntB) throws android.os.RemoteException;
public com.linxtu.demo.api.common.aidl.IDemoRegisterAIDL getDemoApiRegister() throws android.os.RemoteException;
}
关键的函数asInterface返回Proxy类里面有aidl文件的方法,并且调用transact方法。
关键的函数onTransact根据transact传参处理。
三、服务端怎么写
- 重写 IDemoApiManager.Stub 的方法
- 重写 onBind() 方法,返回写好的 IDemoApiManager.Stub
public abstract class DemoApiManagerService extends Service{ IDemoApiManager.Stub mBinder = new IDemoApiManager.Stub(){ @Override public int addTest(int anIntA, int anIntB) throws RemoteException { return anIntA+anIntB; } @Override public IDemoRegisterAIDL getDemoApiRegister() throws RemoteException { // if(demoRegisterService == null){ demoRegisterService = new DemoRegisterService(); } return demoRegisterService; } }; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } }
四、客户端怎么写
- 建立连接,然后在 ServiceConnection 里面通过asInterface获取 IDemoApiManager 对象
- 接着通过它来调用服务端的方法
private static IDemoApiManager demoapi; private static Intent startIntent = new Intent(SERVICE_ACTION_NAME); @Override public void onCreate() { super.onCreate(); mContext = this; startIntent.setPackage(SERVICE_PACKAGE_NAME); if(demoapi == null) { this.startService(startIntent); this.bindService(startIntent, mConn, Context.BIND_AUTO_CREATE); } } private static ServiceConnection mConn = new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { demoapi = null; Log.d(TAG, "onServiceDisconnected"); } public void onServiceConnected(ComponentName name, IBinder service) { demoapi = com.linxtu.demo.api.common.aidl.IDemoApiManager.Stub.asInterface(service); Log.d(TAG, "onServiceConnected"); } };
另外还有一种情况是通过获取系统服务,如下
IBinder b = ServiceManager.getService(Context.XXX);
if(b != null) {
IDemoApiManager demoapi = com.linxtu.demo.api.common.aidl.IDemoApiManager.Stub.asInterface(b);
}
五、小结
通过上面的代码,可以帮助我们看代码时更容易理解。看代码根据三,四小节去查找。具体实现是需要阅读由aidl生成的java文件,也就是二中那一长串代码。有机会再整理。