本文译自:http://developer.android.com/guide/components/aidl.html
AIDL(AndroidInterface DefinitionLanguage)跟你使用的其他的IDLs类似。为了进程间能够互相通信(IPC),它允许你定义客户端和服务端都认可的编程接口。在Android上,通常一个进程不能访问另一个进程内存。所以说,它们需要分解成操作系统能够理解的原始对象,并且把它们编组成跨越边界的对象。编写编组代码是非常麻烦的,因此Android会使用AIDL来处理它。
注意:只有允许不同应用程序的客户端用IPC方式访问服务端,并且想要在服务端处理多线程时,才有必要使用AIDL。如果不需要跨越不同的应用程序来执行并发的IPC处理,就应该通过实现一个Binder来创建接口。或者,如果想要执行IPC处理,但不需要处理多线程,可以使用Messenger类来实现接口。因此,在实现AIDL之前,必须确保你理解Android的BoundServices。
在开始设计AIDL接口之前,要注意AIDL接口的调用是直接的函数调用。你不应该假设相关调用所会发生在哪个线程中。尤其是根据调用是来自本地进程线程,还是远程进程的线程,所发生的处理是不同的:
1.来自本地进程的调用会在与调用者相同的线程中被执行。如果这是主UI线程,那么线程会在AIDL接口中继续执行。如果是另外一个线程,那么调用例程是在服务中要执行代码之一。因此,只有正在访问服务的本地线程,才能够完全控制调用会在哪个线程中执行(但是,这个中情况下,完全不需要使用AIDL,而是应该通过实现Binder来创建接口)。
2.来自远程进程的调用会被分配到一个由平台维护的进程内部的线程池中。你必须为来自未知的、同时发生的多次调用的线程做好准备。换句话说,AIDL接口的实现必须是线程安全的。
3.oneway关键次是用来修饰远程调用行为的。当使用该关键词时,远程调用不是阻塞的,它只是发送事物数据并立即返回。接口的实现最终实现是把普通的远程调用按照Binder线程池的调用规则来接收的。如果oneway是使用在本地调用上,那么不会有任何影响,并且调用依然是异步的。
定义AIDL接口
必须使用Java编程语言的语法来定义AIDL接口,然后把它保存在持有该服务的应用程序和绑定该服务的应用程序的源代码中(在src/目录中)。
在构建每一个包含.aidl文件的应用程序时,AndroidSDK工具会基于.aidl文件生成一个IBinder接口,并把该接口文件保存在gen/目录中。该服务必须正确的实现IBinder接口。然后客户端应用程序才能够绑定该服务,并调用IBinder中的方法来执行进程间通信(IPC)。
按照以下的步骤来创建一个使用AIDL的绑定服务:
1.创建.aidl文件
这个文件定义了带有方法签名的编程接口。
2.实现.aidl文件中定义的接口
AndroidSDK工具基于.aidl文件,用Java编程语言生成该接口。这个接口有一个内部名叫Stub的抽象类,它继承了Binder类,并实现了AIDL接口中定义的方法。必须继承Stub类并实现这些方法。
3.把接口暴露给客户端
实现一个Service,并重写onBind()方法,让它返回Stub类的实现。
警告:在AIDL接口第一次发布之后的任何接口的改变,都必须保持向后的兼容性,以避免使用该服务的其他应用程序的中断。因为为了让其他的应用程序能够访问该服务的接口,就必须把.aidl文件复制到使用该服务的应用程序中,所以就必须保持对初始定义的接口的支持。