Android 进程间通信(IPC)有多种方式,其中 AIDL(Android Interface Definition Language) 是最常用的一种,特别适用于 客户端-服务端(Client-Server)模型,当多个应用或进程需要高效地共享数据或调用方法时,AIDL 是一个很好的选择。
1. AIDL 基本概念
AIDL 允许不同的 Android 进程通过 Binder 机制进行通信。Binder 是 Android 的核心 IPC 机制,它高效、安全,并且支持跨进程对象传递。AIDL 本质上是 定义了一个接口,使得不同进程可以像调用本地方法一样调用远程方法。
AIDL 适用场景
- 当不同进程需要共享数据,并且需要进行方法调用(而不仅仅是发送数据)。
- 需要高性能、低延迟的 IPC 机制(相比 Messenger 或广播)。
- 需要支持多线程访问。
2. AIDL 的工作原理
AIDL 基于 C/S 架构,工作流程如下:
- 定义 AIDL 接口文件(Ixxx.aidl),定义方法签名。
- 编译 AIDL 文件,系统自动生成 Binder 代理类(Stub、Proxy)。
- 服务端实现 AIDL 接口,通过 Stub处理远程调用请求。
- 客户端绑定服务,通过Proxy调用远程方法。
- 数据通过 Binder 传输,完成跨进程通信。
3. AIDL 实践:服务端 & 客户端示例
我们来创建一个 AIDL 服务,提供一个 add(int a, int b) 方法,供客户端调用。
3.1 服务端(Server)实现
- 创建 AIDL 接口
在 app/src/main/aidl/com/example/aidl/IAddService.aidl 文件中:
javascript
package com.example.aidl;
// 定义 AIDL 接口
interface IAddService {
int add(int a, int b); // 远程方法
}
注意:AIDL 只支持以下数据类型:
- 基本类型(int, long, float, boolean 等)
- String、CharSequence
- List(必须是 ArrayList,内部元素类型也要支持 AIDL)
- Map(必须是 HashMap,Key 必须是 String)
- Parcelable(自定义类型需实现 Parcelable)
- 在 Service 中实现 AIDL 接口
新建 AddService.java,继承 Service 并实现 IAddService.Stub。
java
package com.example.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class AddService extends Service {
// 实现 AIDL 接口的 Binder
private final IAddService.Stub binder = new IAddService.Stub() {
@Override
public int add(int a, int b) throws RemoteException {
return a + b; // 远程方法实现
}
};
@Override
public IBinder onBind(Intent intent) {
return binder; // 返回 Binder 实现
}
}
- 注册 Service 到 AndroidManifest.xml
在 AndroidManifest.xml 中声明 Service,并且要暴露给外部进程(exported=true)
xml
<service
android:name=".AddService"
android:exported="true">
<intent-filter>
<action android:name="com.example.aidl.IAddService" />
</intent-filter>
</service>
3.2 客户端(Client)实现
- 复制 AIDL 文件
在客户端项目的 app/src/main/aidl/com/example/aidl/ 目录下,新建 IAddService.aidl,确保包名、方法一致。 - 绑定远程 Service
在 MainActivity.java 中,实现 Service 绑定逻辑:
java
package com.example.aidlclient;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.aidl.IAddService;
public class MainActivity extends AppCompatActivity {
private IAddService addService; // AIDL 接口实例
private boolean isBound = false; // 绑定状态
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
addService = IAddService.Stub.asInterface(service); // 获取 AIDL 代理对象
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
addService = null;
isBound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnCalculate = findViewById(R.id.btnCalculate);
TextView txtResult = findViewById(R.id.txtResult);
// 绑定远程服务
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.aidl", "com.example.aidl.AddService"));
bindService(intent, connection, BIND_AUTO_CREATE);
btnCalculate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isBound && addService != null) {
try {
int result = addService.add(5, 10);
txtResult.setText("Result: " + result);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isBound) {
unbindService(connection);
isBound = false;
}
}
}
- 在 AndroidManifest.xml 申请权限
客户端需要 绑定外部 Service,需在 AndroidManifest.xml 中添加:
xml
<uses-permission android:name="android.permission.BIND_EXTERNAL_SERVICE" />
4. 运行流程
- 启动 服务端(Server) 应用,AddService 开始运行。
- 启动 客户端(Client),自动绑定 AddService。
- 点击按钮,客户端调用 add(5, 10),通过 AIDL 远程执行,返回 15。
5. AIDL 关键知识点总结
- Binder 机制:AIDL 基于 Binder 进行 IPC,高效且安全。
- Stub & Proxy:AIDL 自动生成 Stub(服务端实现)和 Proxy(客户端代理)。
- 多进程通信:使用 bindService() 连接远程 Service,返回接口实例。
- 线程安全:AIDL 默认方法在 Binder 线程池中执行,避免 UI 线程阻塞。
6. AIDL 适用场景 & 限制
适用场景:
高频 IPC(高效传输、方法调用)。 客户端-服务端架构(如媒体播放器、后台计算)。 多进程应用(例如插件化)。
限制:
AIDL 需要序列化/反序列化,比 Messenger 更复杂。 方法调用是同步的,可能导致 UI 卡顿(建议使用
Handler切换线程)。 需要考虑线程安全(多个客户端访问 Service 时需加锁)。
7. 总结
AIDL 是 Android 进程间通信的核心方式之一,适用于 高效、多进程数据共享和方法调用。它基于 Binder 机制,通过 Stub & Proxy 让客户端能像调用本地方法一样调用远程方法。合理使用 AIDL,可以实现高效、稳定的跨进程通信。