前言
最近在看AMS中的源码,发现原理是AIDL进行IPC通讯,特此将基础回顾下,编写了一个简单的DEMO,方便理解。
客户端开启和关闭远程服务
创建两个App
- ServiceApp:包含远程服务
- ClientApp:调用远程服务
ServiceApp
- 创建RemoteAppService服务
public class RemoteAppService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("RemoteAppService onCreate....");
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("RemoteAppService onDestroy....");
}
}
- 注册服务
<service
android:name="com.martin.lib.ipc.remote.RemoteAppService"
android:enabled="true"
android:exported="true"
/>
ClientApp
- 调用ServiceApp的RemoteAppService服务
/**
* 包名为应用程序的报名
*/
private static final String PKG = "com.optimize.lib.ipc";
/**
* 需要启动的服务的全路径名称
*/
private static final String CLS = "com.martin.lib.ipc.remote.RemoteAppService";
Intent intent = new Intent();
intent.setComponent(new ComponentName(PKG,CLS));
findViewById(R.id.open_btn).setOnClickListener(v -> {
startService(intent);
});
findViewById(R.id.close_btn).setOnClickListener(v -> {
stopService(intent);
});
远程服务调用在5.0以后,需要使用显示调用。
- 查看日志

绑定跨进程服务
- bindService:绑定服务
- unbindService:解绑服务
ClientApp
findViewById(R.id.bindRemoteServiceBtn).setOnClickListener(v -> {
bindService(intent,this, Service.BIND_AUTO_CREATE);
});
findViewById(R.id.unBindRemoteServiceBtn).setOnClickListener(v -> {
unbindService(this);
});
- 查看日志

AIDL
AIDL是Android中编写服务向外暴露接口的一种描述语言,服务在外提供接口时需要使用AIDL将接口编写,Android会自动将AIDL文件转换为Java文件,若客户端需要进行接口调用,只需拷贝远程的AIDL文件生成Java代码后使用即可。
ServiceApp
- 定义IRemoteServiceBinder的AIDL文件
// IRemoteServiceBinder.aidl
package com.optimize.lib.ipc;
// Declare any non-default types here with import statements
// IRemoteServiceBinder.aidl
package com.optimize.lib.ipc;
// Declare any non-default types here with import statements
interface IRemoteServiceBinder {
/**
* 远程登录
*/
boolean login(String user,String password);
}
- 在使用Service中使用,定义的AIDL生成的Java类,并在onBind中进行回传。
public class RemoteAppService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new IRemoteServiceBinder.Stub() {
@Override
public boolean login(String data) throws RemoteException {
System.out.println("user:"+user+",password"+password);
}
};
}
}
ClientApp进行远程调用
- 创建AIDL文件夹,将将远程的AIDL文件进行复制到aidl文件夹中,注意文件名称和报名路径必须和ServiceApp完全相同。

- 代码中进行赋值和调用
IRemoteServiceBinder binder = null;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//这里不能做强制类型的转换,因为他们的内存地址是不一样的,所以修改一下. binder = (IRemoteServiceBinder) service;
//正确写法
binder = IRemoteServiceBinder.Stub.asInterface(service);
}
注意,虽然拷贝了相同的文件,但是他们在内存中的地址是不一样的,所以不能进行强转,此时我们需要IRemoteServiceBinder.Stub.asInterface(service);方法来进行类型转换。
- 调用
findViewById(R.id.syncDataBtn).setOnClickListener(v -> {
if (binder != null) {
try {
EditText userNameEdt = findViewById(R.id.userNameEdt);
EditText passwordEdt = findViewById(R.id.passwordEdt);
boolean isSuccess = binder.login(userNameEdt.getText().toString(),
passwordEdt.getText().toString());
if (isSuccess){
System.out.println("login success");
}else {
System.out.println("login failure");
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
- 查看结果

本文通过一个简单的DEMO介绍了AIDL在Android中的应用,详细阐述了如何创建和关闭远程服务、绑定跨进程服务以及客户端如何进行远程调用。通过AIDL定义接口,服务端实现并暴露,客户端调用并转换接口类型,实现了进程间的通信。

被折叠的 条评论
为什么被折叠?



