虽然很多应用都是在一个进程中,但是同样的也有很多应用是运行在不同进程中的,一个进程Crash了并不会影响其他的进程。因此在不同的进程中就需要相互通信了。这就引出了IPC(Inter-Process Communication)的概念。AIDL(Android Interface Definition Language)就是实现IPC的一种方式。
AIDL支持的类型:
基本类型、String、CharSequence、List、Map、Parcelable、对象
AIDL传递基本类型和对象类型流程
1、AIDL传递基本类型
- 新建一个aidl文件
File - New - AIDL - AIDL File
AndroidStudio会生成一个aidl文件夹,在与java包下同包名的目录中存放之前新建的aidl文件。在文件中编写方法,例如
interface MyAidl {
String getName(); // 获取姓名
int getAge(); // 获取年龄
int getPid(); // 获取当前进程,对比是否在同一进程中
}
重新编译,Build - Make Module xxx。
Build成功后会在build/generated/source/aidl/debug/包名下生成一个aidl文件
- 新建一个Service返回binder对象,并在Android Meniferst文件中注册,指定一个进程,注意前面的“:”
<service
android:name=".MyService"
android:process=":myProcess"/>
- 在Service中返回binder对象
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
MyAidl.Stub binder = new MyAidl.Stub() {
@Override
public String getName() throws RemoteException {
return "张三";
}
@Override
public int getAge() throws RemoteException {
return ;
}
@Override
public int getPid() throws RemoteException {
return Process.myPid();
}
};
}
- 在Activity中绑定服务
private MyAidl mAidl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MyService.class);
bindService(intent, connection, Service.BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
try {
mAidl = MyAidl.Stub.asInterface(iBinder);
Log.i("TAG", "Name: " + mAidl.getName() + "\n Age: " + mAidl.getAge() +
"\n RemotePid: " + mAidl.getPid() + "\n CurrentPid:" + Process.myPid());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mAidl = null;
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (connection != null) unbindService(connection);
}
打印Log
根据日志可以看出,的确是不在一个进程中,而且int类型和String类型的数据也成功的传过来了。
2、AIDL传递对象类型
步骤大致和基本类型一致,只是在某些细节上不一样
- 新建aidl文件同基本类型,区别在于aidl中的方法类型。
- 新建一个bean类,实现Parcelable接口。
public class Person implements Parcelable {
private String name;
private int age;
private int pid;
public Person(String name, int age, int pid) {
this.name = name;
this.age = age;
this.pid = pid;
}
protected Person(Parcel in) {
name = in.readString();
age = in.readInt();
pid = in.readInt();
}
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];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
@Override
public int describeContents() {
return ;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeInt(age);
parcel.writeInt(pid);
}
}
- 新建一个与上一步同名的aidl文件,如果是新建一个aidl文件as会提示不能同名,则可以直接New - File就行,在aidl文件中加上parcelable+文件名,p是小写
package com.cc.ui;
parcelable Person;
- 在MyAidl.aidl文件中定义新的方法
package com.cc.ui;
import com.cc.ui.Person;
interface MyAidl {
Person getPersonInfo();
}
注意上面的import,必须将Person.java的路径给导进来。然后再重新编译一下。
- 在Service中返回binder对象
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
MyAidl.Stub binder = new MyAidl.Stub() {
@Override
public Person getPersonInfo() throws RemoteException {
return new Person("张三", , Process.myPid());
}
};
}
- 在Activity中绑定服务
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
try {
mAidl = MyAidl.Stub.asInterface(iBinder);
Person personInfo = mAidl.getPersonInfo();
Log.i("TAG", "Name: " + personInfo.getName() + "\n Age: " + personInfo.getAge() +
"\n RemotePid: " + personInfo.getPid() + "\n CurrentPid:" + Process.myPid());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mAidl = null;
}
};
其他部分与基本类型一致。
Log:
根据日志看出获取成功了。
in out inout
这三个数据流通方式的标签还没研究过。