在 Android 系统的演进中,从 Android 7 到 Android 8,与 ActivityManagerService(AMS)通信的方式确实发生了从代理类方式向 AIDL(Android Interface Definition Language)方式的转变,下面为你详细介绍这两种方式以及切换的原因:
Android 7 及以前:代理类方式
原理
在早期的 Android 版本(如 Android 7 及以前),与 ActivityManagerService 通信主要借助代理类。代理类是一种设计模式,它作为 ActivityManagerService 的远程代理存在于客户端进程中。客户端通过调用代理类的方法,将请求发送到系统进程(包含 ActivityManagerService),代理类会负责处理跨进程通信(IPC)的细节,比如将方法调用转换为合适的消息格式并通过 Binder 机制发送到系统进程。
示例代码结构
以下是一个简化的示例来展示这种代理类的概念:
// 客户端调用的代理类
public class ActivityManagerProxy {
private IBinder mRemote;
public ActivityManagerProxy(IBinder remote) {
mRemote = remote;
}
public void startActivity(Intent intent) {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IActivityManager.descriptor);
intent.writeToParcel(data, 0);
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
} catch (RemoteException e) {
e.printStackTrace();
} finally {
data.recycle();
reply.recycle();
}
}
}
在这个示例中,ActivityManagerProxy 是客户端使用的代理类,它通过 Binder 进行跨进程通信,将 startActivity 的请求发送到 ActivityManagerService。
Android 8 及以后:AIDL 方式
原理
AIDL 是 Android 提供的一种接口定义语言,用于定义客户端和服务端之间的通信接口。在 Android 8 及以后的版本中,与 ActivityManagerService 通信采用 AIDL 方式。开发者只需要定义一个 AIDL 文件,描述客户端和服务端之间的接口方法,然后 Android 工具会自动生成相应的 Java 代码,包括代理类和 Stub 类。客户端通过调用代理类的方法,代理类会将请求封装并通过 Binder 发送到服务端的 Stub 类,Stub 类再调用实际的 ActivityManagerService 方法进行处理。
示例代码结构
-
定义 AIDL 文件(例如
IActivityManager.aidl)
// IActivityManager.aidl
package android.app;
import android.content.Intent;
interface IActivityManager {
int startActivity(in Intent intent);
}
-
Android 工具会自动生成相关的 Java 代码
生成的代码包含IActivityManager接口、Stub类(服务端实现)和代理类(客户端使用)。客户端可以通过如下方式使用:
// 获取 AIDL 接口的代理对象
IActivityManager am = IActivityManager.Stub.asInterface(ServiceManager.getService("activity"));
// 调用方法
am.startActivity(intent);
切换的原因
- 代码生成和维护的便利性:使用 AIDL,Android 工具会自动生成跨进程通信所需的代码,减少了手动编写代码的工作量,降低了出错的可能性,同时也方便了代码的维护和更新。
- 标准化和可读性:AIDL 提供了一种标准化的方式来定义跨进程接口,使得代码更加清晰和易于理解,不同开发者之间的协作也更加顺畅。
- 兼容性和扩展性:AIDL 支持复杂的数据类型和参数传递,能够更好地适应 Android 系统不断发展的需求,提高了系统的兼容性和扩展性。