Android AIDL相關
前言
Android系統中的進程之間不能共享內存,因此,需要提供一些機制在不同進程之間進行數據通信。
AIDL
全稱(Android Interface Definition Langague)
三種類型
AIDL
- IPC(Inter-Process Communication,進程間通信),多線程,多個應用程序。
Binder
- 只有IPC(Inter-Process Communication,進程間通信),沒有多線程,多個應用程序。
Messenger
- 只有IPC(Inter-Process Communication,進程間通信),沒有多線程。
實現步驟
創建.aidl文件
- 跟創建一個接口文件一樣創建.aidl文件。
- Eclipse編譯後會放在gen目錄下。
- Android Studio直接創建AIDL目錄,跟java目錄同級,直接創建AIDL文件。
- Android Studio默認不編譯,需要編譯後纔會在Debug目錄下顯示出來。
實現接口(Implement the interface)
- 創建一個繼承Service的類,裏面創建一個IBinder來實現Aidl.Stub裏面的方法的IBinder類型的變量。
共享接口給客戶端(Expose the interface to clients)
- 將onBind方法返回的IBinder設置成定義的IBinder變量。
客戶端那裏同樣創建一個.aidl文件,同樣的包名。
- 客戶端綁定Service,使用Intent顯示Intent啓動,在5.0以後不支持隱式調用。
Intent intent = new Intent();
// 新版本5.0必須顯式Intent啓動綁定服務
intent.setcomponent(new ComponetName("包名","包名.類名");
- 客戶端綁定Service,
bindService(intent, conn, Context.BIND_AUTO_CREATE);
。 - 客戶端創建ServiceConnection變量,實現接口。
private ServiceConnection conn = new ServiceConnection(){
// 綁定服務的時候
@Overrive
public void onServiceConnected(ComponentName name, IBinder service){
// 拿到遠程服務
iImoocAidl = IImoocAidl.Stub.asInterface(service);
}
// 斷開服務的時候
@Overrive
public void onServiceDisconnected(ComponentName name){
iImoocAidl = null;
}
}
- 服務端的AndroidManifest.xml文件中添加service,需要添加name,exported,enabled,process。
- 客戶端使用接口定義的方法。
注意
- 更新aidl文件的內容要,要卸載後再運行,纔有用。
- 除了默認的類型外,都需要導包。
- 不支持short是因爲序列化添加不了short類型。
AIDL支持的數據類型
基本的數據類型(byte,int,long,char,boolean,float,double,不支持short)
String,CharSequence
List,Map(必須是支持的類型,也就是不支持short,需要設置in或out或inout屬性in List<String> aList
)
Parcelable(需要設置in或out或inout屬性)
服務端創建實現Parcelable的實體類,如Person,創建構造方法、get、set方法,並且重寫未實現的方法。
在
writeToParcel(Parcel dest, int flags)
方法裏面寫入數據。
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
- 創建CREATOR變量,在createFromParcel(Parcel source)方法裏面返回new Person(source)。
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person[] newArray(int size) {
return new Person[size];
}
@Override
public Person createFromParcel(Parcel source) {
return new Person(source);
}
};
- 創建相應的構造方法,並且按順序讀取數據。
public Person(Parcel source) {
// 按順序
this.name = source.readString();
this.age = source.readInt();
}
創建實體類對應的aidl文件,如Person.aidl。
parcelable Person;
在主aidl文件內import對應的實體類,並且創建對應的方法,Parcelable也要設置in或out或inout屬性。
import com.example.aidlservice.Person;
interface AidlTestInterface {
List<Person> add(in Person person);
}
- 設置Service。
private ArrayList<Person> persons;
@Override
public IBinder onBind(Intent intent) {
persons = new ArrayList<Person>();
return iBinder;
}
private AidlTestInterface.Stub iBinder = new Stub() {
@Override
public List<Person> add(Person person) throws RemoteException {
persons.add(person);
return persons;
}
};
將對應的實體類文件,實體類aidl文件,主aidl文件複製到客戶端,包名必須一致。
客戶端調用對應的方法。
AIDL原理
* Stub.asInterface(Ibinder)訪問的是Proxy。
* Proxy通過發送code請求給Stub裏面的OnTransact方法。