這篇主要記錄的是AIDL的基本使用。
主要參考:Android:學習AIDL,這一篇文章就夠了(上)
Android中獨有的進程間通信方式是Binder,前面學習Service的時候就知道,Service服務端返回給客戶端的就是一個Binder,通過這個Binder完成服務端與客戶端之間的通信。
這個服務端和客戶端可以在同一個進程中,也可以在不同的進程中,對于相同的進程中的情況前面已經(jīng)說了就是繼承BInder類并將服務端的Service返回即可,但是對于不同的進程之間通信,這個就不行了,前面已經(jīng)說了使用Messenger,不過只能傳遞消息,使用AIDL能夠?qū)崿F(xiàn)的就多了,可以進行方法調(diào)用。
首先,AIDL,Android Interface Definition Language,Android接口定義語言,簡單的講,就是用來定義接口的。
然后,只需要定義接口就可以了進行進程間通信了么?不能這么說,但是這個語言是Android定義好的,語法也比較簡單,跟java很類似,我們只需要在其中簡單的定義好我們需要的接口,并寫好相應的序列化的類,然后通過IED就會幫我們生成好相應的文件,我們就可以使用這個來進行進程間通信。
使用AIDL進行進程間通信的主要流程:
如果只需要傳遞基本的數(shù)據(jù)類型,那么就沒什么問題,直接寫AIDL接口文件即可,但是如果想傳遞自定義的類對象,那么就需要考慮到序列化的問題,因為基本的數(shù)據(jù)類型默認都是可序列化的,但是我們自己寫的類是不可以的,因此就需要實現(xiàn)Android中的Parcelable接口,至于這個接口的使用,這個在前面學習Intent傳遞對象的時候就已經(jīng)說過了。
首先,需要創(chuàng)建一個實現(xiàn)了Parcelable接口的bean
然后寫這個bean對應的AIDL文件:
// Book.aidl
package com.example.gsq.servicetest.bean;
parcelable Book;
然后寫我們需要的接口AIDL文件:
// BookManager.aidl
package com.example.gsq.servicetest.bean;
import com.example.gsq.servicetest.bean.Book;
interface BookManager {
List<Book> getBookList();
void addBook(in Book book);
}
一定要注意包名的問題!
Book.aidl的包名需要與bean的包名一致
且BookManager.aidl中一定要導入Book.aidl的包(雖然它們已經(jīng)在一個包下)
還有就是服務端與客戶端的AIDL文件的包名也需要一致(不同的應用,所以建議放在單獨的包中)
尤其是使用AS的,一定要注意。
在AS中寫好了AIDL文件以及java bean之后,只需要點Rebuild Project,AS就會自動生成接口的java類:

至于具體的文件內(nèi)容該怎么寫,需要注意的點,開頭的那篇文章里面介紹的很詳細,建議去學習學習。
到這里就可以開始創(chuàng)建Service服務端了
首先創(chuàng)建一個BookManager.Stub的實例,在其中實現(xiàn)我們前面定義的接口,然后在onBind中將這個實例返回給客戶端。
public class MyService3 extends Service {
//CopyOnWriteArrayList支持冰法讀寫,確保線程同步,其中的方法都是synchronized的
private CopyOnWriteArrayList<Book> bookList = new CopyOnWriteArrayList<>();
private final BookManager.Stub bookManager = new BookManager.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
if(bookList == null){
bookList = new CopyOnWriteArrayList<>();
}
return bookList;
}
@Override
public void addBook(Book book) throws RemoteException {
if(bookList == null){
bookList = new CopyOnWriteArrayList<>();
}
if(book != null && !bookList.contains(book)){
bookList.add(book);
}
}
};
@Override
public IBinder onBind(Intent intent) {
Log.i("test_out","----->onBind");
bookList.add(new Book("serverbook", "ser"));
return bookManager;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("test_out","----->onUnbind");
return true;
}
}
我們還可以在service創(chuàng)建的時候進行一些數(shù)據(jù)的初始化等。
然后是客戶端,通過ServiceConnection獲取到服務端傳來的Binder,轉(zhuǎn)換為BookManager,然后就可以進行服務端的方法調(diào)用了。
public void addBook(){
try {
bookManager.addBook(new Book("book1", "tom"));
bookManager.addBook(new Book("book2", "jack"));
for(Book b : bookManager.getBookList()){
Log.i("test_out","----->" + b.toString());
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
bookManager = BookManager.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("test_out","----->onServiceDisconnected");
}
};
程序運行的記過如下:
服務端:

客戶端點擊對了addBook的按鈕之后:

只是寫了一下AIDL的基本使用,由于剛開始學,理解不夠深入,有不正確的地方請批評指正。