📦 AIDL是什么?
想象你要给隔壁楼的小伙伴传纸条,但你们用不同的语言写字。这时候就需要一个"翻译纸条的协议"——这就是AIDL(Android接口定义语言)。它帮不同APP之间"说同一种话",实现跨进程通信。
📚 AIDL支持的数据类型
🔍 类型支持对照表
| 数据类型 | 快递比喻 | 是否支持 | 注意事项 |
|---|---|---|---|
| 基本类型 | 小件包裹 | ✅ | 直接使用 |
| String/CharSequence | 信件 | ✅ | 自动转码 |
| List/Map | 标准货箱 | ✅ | 实际收到ArrayList/HashMap |
| Parcelable | 定制包装箱 | ✅ | 必须实现接口 |
| AIDL接口 | 跨站对讲机 | ✅ | 需单独定义.aidl文件 |
| FileDescriptor | 保险箱钥匙 | ✅ | 需用ParcelFileDescriptor包装 |
| IBinder | 员工通行证 | ✅ | 直接传递原始Binder对象 |
| 基本类型数组 | 整箱矿泉水 | ✅ | int[]、long[]等直接支持 |
| Parcelable数组 | 定制货箱集装箱 | ✅ | 需元素实现Parcelable |
🎓 自定义包裹教学:Student类
想寄送学生信息?需要三步:
- 实现Parcelable接口(给档案袋贴快递单)
java
Copy
public class Student implements Parcelable {
int age;
String name;
// 必须实现打包/解包方法
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
}
// 创建解包工具
public static final Creator<Student> CREATOR = ...;
}
- 声明.aidl文件(告诉快递公司这个包裹怎么处理)
java
Copy
parcelable Student; // 就像在快递单上写"易碎品"
🏪 服务端开店指南
- 继承Stub类(就像开店要准备商品)
java
Copy
public class HelloService extends IHelloService.Stub {
// 实现各种服务方法
public int printStudent(Student student) {
Log.d(TAG, "收到学生:" + student.name);
}
}
- 注册服务(挂招牌)
java
Copy
ServiceManager.addService("hello", new HelloService()); // 在服务大厅挂上"hello"招牌
🛒 客户端购物指南
- 找服务(按招牌找店)
java
Copy
IBinder binder = ServiceManager.getService("hello"); // 找到"hello"店铺
IHelloService svr = IHelloService.Stub.asInterface(binder); // 拿到购物小票
- 疯狂下单(调用各种方法)
java
Copy
// 寄送普通包裹
svr.sayhello_to("老王");
// 寄送定制包裹
Student stu = new Student();
stu.name = "小明";
svr.printStudent(stu);
// 寄送集合包裹
List<String> wishList = new ArrayList<>();
wishList.add("想要PS5");
svr.printList(wishList);
🔧 编译运行小贴士
- 用
aidl命令生成通信代码(自动生成翻译手册) - 把服务端和客户端打包成jar(就像把店铺和顾客APP分开)
- 通过ADB命令启动(模拟两个APP的通信)
💡 关键理解
📚 原来 Binder 支持这么多数据类型! 让我们用快递站的比喻来分类理解这些"包裹类型"的用途:
🚚 基础小件包裹(基本类型)
-
类型:
boolean、byte、char、int、long、float、double -
特点:轻量高效,像寄送数字纸条
-
示例:
java Copy service.setSwitch(true); // 开关状态 service.sendCode(1001); // 状态码 service.calculate(3.14, 2.0); // 浮点运算
📨 标准文件袋(常用对象)
- String:文字信息(如用户昵称)
- List:有序集合(购物清单)
- FileDescriptor:文件句柄(快递保险箱钥匙)
- PersistableBundle:持久化数据包(带封条的文件袋)
🎁 定制包裹(Parcelable对象)
-
android.os.Parcelable:必须实现打包/解包方法
-
实战场景:
java Copy // 定义用户信息包裹 public class User implements Parcelable { String name; int age; // 实现 writeToParcel 和 CREATOR } // 跨进程传递 service.updateUser(user);
🔑 特权通行证(Binder相关)
-
T extends IBinder:传递 Binder 对象本身
-
使用场景:
java Copy // 传递系统服务的 Binder 引用 IBinder clipboardBinder = service.getSystemBinder(); // 获得剪贴板服务代理 IClipboard clipboard = IClipboard.Stub.asInterface(clipboardBinder);
📦 集装箱货柜(数组与泛型)
-
Arrays (T[]):支持基本类型和 Parcelable 数组
-
注意:
java Copy // 正确用法 int[] ids = {1001, 1002, 1003}; Student[] students = new Student[3]; // 错误用法(需用 ArrayList 替代) // List<String> list = Arrays.asList("A", "B");
💡 为什么需要这么多类型?
- 效率优化:基本类型直接传递二进制数据,无需序列化
- 场景覆盖:从简单状态到复杂对象,从临时数据到持久化存储
- 系统集成:
PersistableBundle用于系统级数据持久化,FileDescriptor实现高效文件传输
🚀 开发指南
-
选型策略:
- 简单数据 → 基本类型
- 复杂对象 → 实现 Parcelable
- 跨服务调用 → 传递 IBinder
- 大文件 → FileDescriptor
-
避坑技巧:
- 避免传递大数据量的数组(改用分块传输)
- 谨慎传递 IBinder(需权限校验)
- PersistableBundle 适合系统备份场景
这些类型共同构成了 Android 跨进程通信的"物流网络",让数据像快递包裹一样安全高效地穿梭于应用之间!🎯