最近做的项目中有需要到进程间通讯,之后通过比对之后选择了 AIDL 作为进程之间的通讯协议。下面简单记录一下关于 AIDL 这方面的一些开发调研与经验。
官方文档: https://developer.android.com/guide/components/aidl#Calling
调研的技术点:
- 支持多种数据类型。如:int,String,基本数据类型,实现 Parcelabel 对象等等。
- 可以实现一个进程同时对接多个 APK。
- 传递对象
- 对象.java 对象.aidl 这两个文件需要在同一个包名下。
具体的操作流程:
服务端 Server:
- 在清单文件中注册服务。
<service android:name="com.example.edwardadmin.service.RmoteService">
<intent-filter>
<action android:name="android.intent.action.RESPOND_AIDL_MESSAGE"></action>
</intent-filter>
</service>
- 在文件夹创建 AIDL File
- 自动生成的 interface.aidl
// 需要手动导入对象的包名
interface IRomteAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
//基本类型
String getPersonUserName();
String getPersonUserAge();
//设置接口
void setPersonInfo(String name,String age);
//获取对象
Person getPerson();
}
- 创建服务 server
public class RmoteService extends Service {
private static final String TAG = "RmoteService";
private Person mPerson;
private String mUserName;
private String mUserAge;
@Override
public void onCreate() {
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind Service success!");
mPerson = new Person("test test ", "24");
return new RomteBinder();
}
// 实现定义的 Stub 接口
class RomteBinder extends IRomteAidlInterface.Stub {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public String getPersonUserName() throws RemoteException {
mUserName = mPerson.getmUserName();
Log.d(TAG, "Person mUserName = " + mUserName);
return mUserName;
}
@Override
public String getPersonUserAge() throws RemoteException {
mUserAge = mPerson.getmUserAge();
Log.d(TAG, "Person mUserAge = " + mUserAge);
return mUserAge;
}
@Override
public void setPersonInfo(String name, String age) throws RemoteException {
mPerson = new Person(name, age);
}
@Override
public Person getPerson() throws RemoteException {
return new Person("对象name","对象age");
}
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
- 传输对象类型,必须实现 Parcelable 接口
因为在 AIDL 传输对象数据时,是要进行序列化和反序列化。所以需要实现 Parcelable 接口。
public class Person implements Parcelable {
private String mUserName;
private String mUserAge;
public Person(String username, String userage) {
mUserName = username;
mUserAge = userage;
}
public String getmUserName() {
return mUserName;
}
public String getmUserAge() {
return mUserAge;
}
@Override
public String toString() {
return super.toString();
}
protected Person(Parcel in) {
mUserName = in.readString();
mUserAge = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mUserName);
dest.writeString(mUserAge);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}
- 实体类的必须和 aidl 放在同样的包名下
客户端 Client
- 把服务端的 aidl 部分拷贝到客户端,同样的目录结构。
- 绑定服务,需要服务端的服务类路径,以及进程的包名
private void bindService() {
Intent serviceIntent = new Intent();
serviceIntent.setAction(BIND_SERVICE_ACTION);
serviceIntent.setComponent(new ComponentName("com.example.edwardadmin.aidlserver", "com.example.edwardadmin.service.RmoteService"));
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
Log.d(TAG, "bindService");
}
- 在服务绑定成功之后,生成 IRomteAidlInterface
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
iRomteAidlInterface = IRomteAidlInterface.Stub.asInterface(iBinder);
Log.i(TAG, "onServiceConnected: " + componentName);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
iRomteAidlInterface = null;
Log.i(TAG, "onServiceDisconnected: ");
}
};
- 通过 IRomteAidlInterface 对象以及定义的 Stub 接口,进行通讯。
好了,AIDL 通讯就简单介绍到这里,具体如何定义接口就需要看需求了。