AIDL用于跨进程数据共享。
1、创建AIDL文件
AIDL(android Interface Definition Language)来定义远程接口,语法和Java接口相似,但有如下几个差异:
1)、AIDL定义接口的源代码必须以.aidl结尾
2)、AIDL接口中的用到的数据类型,除了基本类型、String、List、Map、CharSequence之外,其他类型全部都需要导包,即使他们在同一个包中也需要导包。
package com.example.entity;
import com.example.entity.Pet;
import com.example.entity.Person;
interface Ipet
{
//定义一个Person对象作为一个传入参数
List getPets(in Person owner);
}
定义好AIDL接口后,ADT工具会自动在gen目录下生成一个.java接口,该接口中包含一个Stub内部类,该内部类实现了IBinder、Ipet两个接口,这个Stub类将会作为远程Service的回调类,他实现了IBinder接口,因此可作为Service的onBind()方法的返回值。
2、将接口暴露给客户端
定义好AIDL接口后,接下来就可定义一个Service实现类,该service的onBind()方法返回的IBinder对象应该是ADT生成的Ipet.Stub的子类的实例。
public class MyBinder extends Stub {
@Override
public List getPets(Person owner) throws RemoteException {
return pets.get(owner);
}
}
该service类开发完成之后,接下来在AndroidManifest.xml文件中配置该service,可定义action的值。
3、客户端访问AIDL Service
AIDL接口定义了两个进程之间的通信接口,因此不仅服务器需要AIDL接口,客户端同样需要前面定义的AIDL接口,因此开发客户端的第一步就是讲Service端的AIDL接口文件复制到客户端应用中,复制到客户端后ADT工具会为AIDL接口生成相应的实现。
实现步骤:
1)、创建ServiceConnection 对象
2)、以ServiceConnection对象作为参数,调用Context的bindService()方法绑定远程Service即可。
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
iService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 返回远程service的onBind方法Ibinder对象的代理
iService = Ipet.Stub.asInterface(service);
}
};
Intent service = new Intent("com.example.SERVICE_ACTION");
bindService(service, conn, BIND_AUTO_CREATE);
可以传递自定义类型的。(疯狂Android:P387)
5、其他
AIDL定义时的注意事项:
(1)接口名和aidl文件名相同.
(2)接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static.
(3)AIDL默认支持的类型包话java基本类型(int,long,boolean等)和(String,List,Map,CharSequence),使用这些类型时不需要import声明.对于List和Map中包含的元素类型必须是AIDL支持的类型.如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口.
(4)自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即使在同一个包中.
(5)在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数.
(6)Java原始类型默认的标记为in,不能为其它标记.
(7)oneway 关键字的使用:当接口使用oneway关键字修饰时,表示接口在远程调用时是不会block的,即接口调用时发送完transaction数据后立即返回而不会等待远端的结果。注意,这只针对IPC的调用,同样的接口如果是在同一进程内部被调用的话,oneway关键字不起任何效果,方法该阻塞就阻塞。
AIDL只支持接口方法,不能公开static变量。
抛出的异常是不能返回给调用者(跨进程抛异常处理是不可取的)。但是如果服务端有异常,客户端会收到RemoteException??