AIDL (Android Interface Definition Language) 是一種接口定義語言,用於生成能夠在Android設備上兩個進程之間進行PC的代碼。若是在一個進程中(例如Activity)要調用另外一個進程中(例如Service)對象的操做,就可使用AIDL生成可序列化的參數,來完成進程間通訊,也就是說,爲了簡化應用層進行IPC操做,Android提供了AIDL這門語言,在學習AIDL這門語言以前,咱們來看一下Android中IPC的具體流程。java
Client跟Proxy進行交互的數據不須要進行序列化,可是Proxy跟Server進行交互的時候必須進行序列化跟反序列化android
其實咱們在實際進行IPC的時候並不須要關注Proxy以及Binder Driver,上述模型能夠再次進行抽象bash
client端:BpBinder.transact()來發送事務請求;
server端:BBinder.onTransact()會接收到相應事務。app
AIDL默認支持以下數據類型:ide
若是定義的類型不是AIDL默認支持的類型,則須要使用Parcelable進行序列化。一類是用來定義parcelable對象,以供其餘AIDL文件使用AIDL中非默認支持的數據類型的。學習
AIDL的文件後綴名爲.aidl,並非以前的.java,不過在使用AIDL進行通訊的過程當中,
aidl文件只是用來定義數據類型跟接口。ui
public class People implements Parcelable {
private int age;
private String gender;
private String hobby;
//此處省略若干行代碼
}複製代碼
package com.wustor.aidl;
// Declare any non-default types here with import statements
parcelable People;複製代碼
package com.wustor.aidl;
// Declare any non-default types here with import statements
import com.wustor.aidl.People;
interface PeopleManager {
List<People> getPeople();
void addPeople(in People people);
}複製代碼
Android系統會在".\app\build\generated\source\aidl\debug\com\wustor\aidl"的目錄下生成一個PeopleManager.java文件,這個類就是AIDL的核心,這個類是一個接口,下面先看一下這個接口的結構圖:this
PeopleManager內部實現了PeopleManager.aidl的兩個方法,而且在內部建立了一個叫Stub的內部類,同時Stub也本身維護了一個叫作Proxy的內部類,經過前面對Binder機制的原理分析,咱們其實能夠很明確的知道,Proxy就是服務端的代理類,他做爲一個 中間代理,承載了Client與Server之間的轉化,而Stub類的onTransact方法就是用來接收Proxy的輸入而且把請求結果返回,從而達到代理的做用,因此分析AIDL實際上只須要注重分析一下asInterface,onTransact這兩個方法以及Proxy代理類便可。 spa
@Override
public android.os.IBinder asBinder() {
return this;
}複製代碼
返回當前Binder對象線程
此方法位於Client端
/** * Cast an IBinder object into an com.wustor.aidl.PeopleManager interface, * generating a proxy if needed. */
public static com.wustor.aidl.PeopleManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//查看本地是否存在這個類,不存在的話就從新建立
if (((iin != null) && (iin instanceof com.wustor.aidl.PeopleManager))) {
return ((com.wustor.aidl.PeopleManager) iin);
}
return new com.wustor.aidl.PeopleManager.Stub.Proxy(obj);
}複製代碼
queryLocalInterface
public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}複製代碼
首先會調用queryLocalInterface來判斷descriptor跟mDescriptor是否相等,咱們經過查看Binder的源碼能夠看到descriptor就是當前PeopleManager的類名,那麼經過傳遞過來的Binder對象查詢這個類名,實際上就是判斷Server端的BookManager跟Client是否是相同,若是相同就說明Client跟Server是在同一個進程,若是在同一個進程,那麼就直接返回當前的IInterface ,不然返回null,那麼Client端就會本身建立一個Proxy的代理類。
getPeople()
static final int TRANSACTION_getPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
@Override
public java.util.List<com.wustor.aidl.People> getPeople() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.wustor.aidl.People> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//調用transact方法,傳遞參數
mRemote.transact(Stub.TRANSACTION_getPeople, _data, _reply, 0);
_reply.readException();
//拿到返回結果
_result = _reply.createTypedArrayList(com.wustor.aidl.People.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
//返回參數給Client
return _result;
}複製代碼
在Client調用,執行Transact方法,當前線程阻塞,服務端的onTransact方法會被調用,從reply中拿到返回值後,線程繼續執行。
addPeoplet
@Override
public void addPeople(com.wustor.aidl.People people) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((people != null)) {
_data.writeInt(1);
people.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addPeople, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}複製代碼
在Client執行,跟getPeople()方法基本一致,惟一的區別是此方法沒有返回值,因此不須要回寫Client
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getPeople: {
data.enforceInterface(DESCRIPTOR);
java.util.List<com.wustor.aidl.People> _result = this.getPeople();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addPeople: {
data.enforceInterface(DESCRIPTOR);
com.wustor.aidl.People _arg0;
if ((0 != data.readInt())) {
_arg0 = com.wustor.aidl.People.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addPeople(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}複製代碼
運行在Server端,當Client端發起跨進程請求的時候,系統底層會返回Proxy代理,而後經過代理執行Client的方法,就會調用此方法。注意這個方法會從data取傳遞過來的參數,而後經過code判斷須要執行哪個方法,執行完畢後,就返回值寫入reply中,此方法的返回值代表IPC請求是否成功。
經過分析AIDL的原理,從而能夠進一步理解Binder機制,總結一下,Android中利用Binder機制。
經過觀察這張圖,咱們能夠AIDL底層對Binder機制進行了封裝,讓Android中的IPC通訊機制更加簡單方便,固然,咱們也能夠本身動手寫,固然Android中還有別的不少IPC通訊方式,例如Messenger等,。若是想實現Binder機制進行通訊,只須要Server(在Android裏面大多數使用Service來建立一個Server)端返回一個Binder對象,而後將調用asInterface將Binder對象傳遞過來便可。