AIDL,即Android Interface Definition Language,Android接口定义语言。这门语言是为了实现进程间通信。每一个进程都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行自己的操作,而AIDL,就是两个进程之间沟通的桥梁。
AIDL的具体使用步骤:
1.在src文件夹下右键,选择新建aidl文件,这里新建了一个aidl文件;新建完以后,会在main文件下生成一个aidl的文件夹,aidl文件夹下的目录结构和java文件夹下的目录结构一样。Baidl文件中会有一个默认方法,除掉这个默认方法,只声明一个parcelable数据类型,这个文件就成为声明Parcelable数据类型的AIDL文件。
2.自定义类并实现Parcelable接口,注意自定义类在java文件夹下的目录与aidl文件夹下的目录保持一致。
3.另外新建aidl文件来定义能被客户端调用的接口
4.Rebuild project,系统会帮我们生成一个与AIDL文件同名的java文件
5.定义一个Service类,通过这个Service将接口提供给外部
6.在注册文件中新增Service服务
aidl文件支持的数据类型包括:
- 八种基本数据类型:byte、char、short、int、long、float、double、boolean
- String、CharSequence
- 实现了Parcelable接口的数据类型
- List类型。List承载的数据必须是AIDL支持的类型,或者是其他声明的AIDL对象
- Map类型。Map承载的数据必须是AIDL支持的类型,或者是其他声明的AIDL对象
在使用其他声明的AIDL对象的时候必须要导包,即使要使用的AIDL对象文件和当前正在编辑的aidl文件在同一个文件夹下。
aidl文件可以分为两类,一类用来声明实现了Parcelable接口的数据类型,以供其他AIDL文件使用那些非默认支持的数据类型。还有一类是用来定义接口方法,声明要暴露哪些接口给客户端调用。
参考:https://www.jb51.net/article/216836.htm
transact 和onTransact需要先聊聊iBinder
1.Android的跨进程调用就是通过IBinder实现的,IBinder是远程对象的基本接口,是为高性能而设计的轻量级远程调用机制的核心部分。但它不仅用于远程调用,也用于进程内调用。这个接口定义了与远程对象交互的协议。不要直接实现这个接口,而应该从Binder派生。
2.IBinder的主要API是transact(),与它对应另一方法是Binder.onTransact()。第一个方法使你可以向远端的IBinder对象发送发出调用,第二个方法使你自己的远程对象能够响应接收到的调用。IBinder的API都是同步执行的,比如transact()直到对方的Binder.onTransact()方法调用完成后才返回。
3.通过transact()发送的数据是Parcel,Parcel是一种一般的缓冲区,除了有数据外还带有一些描述它内容的元数据。元数据用于管理IBinder对象的引用,这样就能在缓冲区从一个进程移动到另一个进程时保存这些引用。这样就保证了当一个IBinder被写入到Parcel并发送到另一个进程中,如果另一个进程把同一个IBinder的引用回发到原来的进程,那么这个原来的进程就能接收到发出的那个IBinder的引用。这种机制使IBinder和Binder像唯一标志符那样在进程间管理。
4.系统为每个进程维护一个存放交互线程的线程池。这些交互线程用于派送所有从另外进程发来的IPC调用。例如:当一个IPC从进程A发到进程B,A中那个发出调用的线程(这个应该不在线程池中)就阻塞在transact()中了。进程B中的交互线程池中的一个线程接收了这个调用,它调用Binder.onTransact(),完成后用一个Parcel来做为结果返回。然后进程A中的那个等待的线程在收到返回的Parcel后得以继续执行。实际上,另一个进程看起来就像是当前进程的一个线程,但不是当前进程创建的。
5.要实现IBinder来支持远程调用,应从Binder类派生一个类。Binder实现了IBinder接口。但是一般不需要直接实现此类,而是跟据你的需要由开发包中的工具生成,这个工具叫AIDL。你通过AIDL语言定义远程对象的方法,然后用AIDL工具生成Binder的派生类,然后就可使用之。当然,你也可以直接从Binder类派生以实现自定义的RPC调用,或只是实例化一个原始的Binder对象直接作为进程间共享的令牌来使用。