Android进程间通信——AIDL

AIDL(Android Interface Definition Language)是Android中用于定义客户端和服务端之间通信接口的一种接口定义语言。它允许你定义客户端和服务的通信协议,用于在不同的进程间同一进程的不同组件间进行数据传递。AIDL通过定义接口和数据类型,让Android应用中的组件能够跨进程通信(IPC),即所谓的远程方法调用(Remote Procedure Call, RPC)。

img

Binder

整个Linux系统分为用户空间和内核空间 用户空间的资源是独立的 内核空间的资源是共享的。Binder可以通过应用mmap技术(Linux通过将一个虚拟内存区域与磁盘上的对象关联起来,以初始化这个虚拟内存区域的内容,这个过程称为内存映射mmap)将内核空间的虚拟地址和server端的虚拟地址映射到同一块物理内存上:

binder的框架图如下:

binderframework

AIDL工作原理

由于跨进程之间通信的复杂性,Android层面上为开发者提供了AIDL工具,方便开发者开发接口

Android中,不同的应用和组件通常运行在各自的进程中,为了让这些分隔的组件能够相互通信,Android中提供了AIDL作为定义通信接口的工具。当需要使用AIDL的时候,需要定义一个接口,接口中包含可供客户端调用的方法。Android构建系统会根据这个AIDL接口文件生成Java接口代码,然后服务端实现这个接口,客户端通过绑定服务并调用这些接口中定义的方法来实现跨进程通信。

使用AIDL进行IPC通信大致有以下步骤:

  1. 定义接口:首先,你需要定义一个接口,这个接口描述了远程服务提供的方法。这个接口使用 AIDL 语言编写,其中包含了需要在不同进程之间进行通信的方法签名。
  2. 生成代理类:接下来,Android SDK 提供了一个工具,称为 AIDL 编译器,它会根据你定义的接口生成对应的代理类。这个代理类实现了 android.os.IInterface 接口,作为客户端和服务端之间通信的桥梁。
  3. 实现接口:在服务端,你需要实现之前定义的接口,并提供相应的方法逻辑。这些方法会被远程客户端调用。
  4. 暴露服务:服务端创建一个服务,并在其onBind方法中返回实现了AIDL接口的实例
  5. 绑定服务:客户端需要绑定到远程服务,以便通过代理类进行通信。这通常通过 bindService() 方法实现。
  6. 远程调用:一旦客户端绑定到远程服务,它就可以通过代理类调用远程服务中定义的方法。当客户端调用这些方法时,实际上是在远程服务的进程中执行相应的代码逻辑。
  7. 数据传输:在 AIDL 中,参数和返回值需要是 Parcelable 类型,这样它们才能在不同进程之间进行序列化和反序列化。Parcelable 是 Android 提供的一种序列化机制,它允许对象在不同进程之间进行传输。

数据类型

而且在AIDL文件中,不是所有数据类型都是可以使用的,支持的数据类型如下:

  • Java 编程语言中的所有基本数据类型(byte、char、short、int、long、float、double、boolean)
  • String和CharSequence;
  • List:只支持ArrayList,里面每个元素都必须能够被AIDL支持;
  • Map:只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value;
  • Parcelable:所有实现了Parcelable接口的对象;

注意:

  • 当需要传递对象时,则对象必须实现Parcelable接口
  • 所有非原语参数均需要指示数据走向的方向标记。这类标记可以是 in、out 或 inout。 原语默认是in,这里应该考虑一下是用什么原语标记,如果是inout的开销大
    • in : 客户端流向服务端
    • out : 服务端流向客户端
    • inout : 双向流通

什么是stub

stub在AIDL中充当了消息传递的桥梁,负责将客户端的请求传递给服务端,并将服务端的响应传递回客户端。
简单的来说就是AIDL的出站口

什么是proxy

proxy在AIDL中充当了客户端与服务端交互的代理角色。它实现了AIDL接口,并负责将客户端的方法调用转发给stub对象,以便客户端与服务端进行跨进程通信。
简单的来说就是AIDL的进站口

oneway关键字

oneway关键字用于修改远程调用的行为,应用该关键字远程调用不会阻塞,是异步调用。当客户端调用服务端的方法并且不需要获取其返回结果时,使用异步调用可以提升客户端的执行效率。

线程安全

AIDL方法是在服务端的Binder线程池中执行,多个客户端同时进行链接且操作数据时可能存在多个线程同时访问的情况,因此我们需要在服务端的AIDL方法中处理多线程同步问题。

谷歌文档

定义和实现AIDL接口:Android 接口定义语言 (AIDL) | Background work | Android Developers (google.cn)

https://source.android.com/docs/core/architecture/aidl?hl=zh-cn


Android进程间通信——AIDL
https://chujian521.github.io/blog/2024/04/27/Android进程间通信——AIDL/
作者
Encounter
发布于
2024年4月27日
许可协议