雖然很多應用都是在一個進程中,但是同樣的也有很多應用是運行在不同進程中的,一個進程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 25;
}
@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 0;
}
@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("張三", 25, 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
這三個數據流通方式的標籤還沒研究過。