Demo 地址
https://github.com/jutao/aidl
AIDL客戶端
什么是AIDL
在 Android中,每一個應用程序獨自擁有一個虛擬機,這樣做雖然保證了進程之內數據的安全性,保證一個應用程序的數據不受其他應用程序的影響,也保證了一個應用程序掛掉了不至于影響其他應用程序。但是這樣也造成了一個應用程序和另外一個應用程序沒辦法直接進行通訊。AIDL 的作用就是使來自不同應用的客戶端跨進程通信訪問你的 Service。
AIDL 是 Android Interface Definition Language 的縮寫,就是安卓內部通信接口描述語言。關于 AIDL的描述和用法我主要參考了Google 的官方API,找到一個中文的,鏈接:http://www.android-doc.com/guide/components/aidl.html。需要補充的是,API里描述AIDL支持Java語言中的所有基本數據類型,但是經過查證和實驗,實際上 AIDL 是不支持Short類型的。
AIDL用法
創(chuàng)建 AIDL 接口

如果是 Eclipse 的話需要創(chuàng)建 File 并且不要忘記自己打上后綴 .aidl。
寫 AIDL 接口
AIDL 的用法基本和寫普通 Java 接口相同,需要注意的是包名一定要自己檢查一下,還有導包也要自己寫一下。
package com.example.jutao.aidl;
interface IServiceAidl {
//計算兩個數的和
int add(int num1,int num2);
}
寫完之后需要注意,如果你寫的 AIDL 接口正確,那么 Ecipse 是會自動編譯的,而 Android Studio 需要手動編譯,編譯按鈕如下圖所示:

編譯通過后,Android Studio 所生成的文件在

寫 Service
//當客戶端綁定到該服務的時候
@Override public IBinder onBind(Intent intent) {
//當別人綁定服務的時候,就會得到AIDL接口
return iBinder;
}
IBinder iBinder = new IServiceAidl.Stub() {
@Override public int add(int num1, int num2) throws RemoteException {
Log.d("TAG", "收到服務端請求,求出" + num1 + "和" + num2 + "的和");
return num1 + num2;
}
};
<!-- exported 是否支持其它應用調用當前組件 -->
<!-- enabled 這個屬性用于指示該服務是否能夠被實例化。如果設置為true,則能夠被實例化,否則不能被實例化。默認值是true -->
<service
android:name="com.example.aidl_service.RemoteService"
android:enabled="true"
android:exported="true" >
</service>
寫客戶端
客戶端的主要功能是用戶通過界面輸入兩個數字,點擊遠程計算按鈕后通過服務端代碼計算出結果返回給客戶端并顯示。

點擊按鈕后

需要注意的是,客戶端也需要有一模一樣的 AIDL 包,連包名都要一模一樣??!
//1、獲取服務端
Intent intent = new Intent();
//Android 5.0之后不支持隱式意圖,必須是顯式意圖來啟動綁定服務
intent.setComponent(
new ComponentName("com.example.jutao.aidl", "com.example.jutao.aidl.RemoteService"));
//第三個參數是一個flag,綁定時自動啟動
bindService(intent, conn, Context.BIND_AUTO_CREATE);
conn的定義:
ServiceConnection conn = new ServiceConnection() {
//綁定服務時
@Override public void onServiceConnected(ComponentName name, IBinder service) {
//拿到了遠程的服務
iServiceAidl = IServiceAidl.Stub.asInterface(service);
}
//當服務斷開時
@Override public void onServiceDisconnected(ComponentName name) {
//回收資源
iServiceAidl = null;
}
};
AIDL 自定義類型

AIDL 默認支持的數據類型如上圖所示,雖然支持List類型,但是需要 在List前注明輸入List還是輸出List,下面的例子會講到。
首先 person 類要實現 Parcelable 接口,詳細代碼可以在我開頭貼的Demo里看。
import com.example.jutao.aidl.Person;
interface PersonAidl {
List<Person> add(in Person person);
}
parcelable Person;
public class PersonService extends Service {
private ArrayList<Person> persons;
public PersonService() {
}
@Override public IBinder onBind(Intent intent) {
persons = new ArrayList<Person>();
return iBinder;
}
private IBinder iBinder = new PersonAidl.Stub() {
@Override public List<Person> add(Person person) throws RemoteException {
persons.add(person);
return persons;
}
};
}

可以看到,我每次輸出的都是 persons 這一List,這是通過服務端返回的,說明我傳輸過去的值已經被服務端接收并存儲。