AIDL介紹
我們通常比較熟悉Android應(yīng)用程序中進(jìn)行跨進(jìn)程訪(fǎng)問(wèn)的組件BroadcastReceiver和ContentProvider,另外一個(gè)Android應(yīng)用程序組件Service也可以,這種可以跨進(jìn)程訪(fǎng)問(wèn)的服務(wù)稱(chēng)為AIDL服務(wù)。
AIDL (Android Interface Definition Language)是 Android 提供的一種機(jī)制,允許通過(guò)跨進(jìn)程的接口實(shí)現(xiàn)不同應(yīng)用或進(jìn)程之間的通信。
AIDL 的基本原理
在 Android 中,每個(gè)應(yīng)用運(yùn)行在自己的獨(dú)立進(jìn)程中。當(dāng)需要跨進(jìn)程進(jìn)行通信時(shí),應(yīng)用間的對(duì)象無(wú)法直接傳遞和共享,必須通過(guò) AIDL 接口進(jìn)行通信。AIDL 會(huì)自動(dòng)生成接口代碼來(lái)處理復(fù)雜的數(shù)據(jù)類(lèi)型和方法調(diào)用,從而使兩個(gè)進(jìn)程可以在不直接共享內(nèi)存的情況下進(jìn)行數(shù)據(jù)交換。
AIDL 使用類(lèi)似于 Java 接口的語(yǔ)法,并定義一個(gè)接口來(lái)描述客戶(hù)端和服務(wù)端之間的交互方法。Android 系統(tǒng)通過(guò)這一接口來(lái)生成代理類(lèi)和實(shí)際實(shí)現(xiàn)類(lèi),從而實(shí)現(xiàn)跨進(jìn)程調(diào)用。
AIDL 的基本工作流程
- 定義 AIDL 接口:在服務(wù)端應(yīng)用中,定義一個(gè) AIDL 文件,描述客戶(hù)端和服務(wù)端之間的通信接口。
- 生成 Java 接口:使用 AIDL 文件,Android 編譯器會(huì)自動(dòng)生成對(duì)應(yīng)的 Java 接口代碼。該代碼會(huì)包含一個(gè)接口類(lèi)(Stub 類(lèi))和一個(gè)客戶(hù)端代理類(lèi)(Proxy 類(lèi))。
- 實(shí)現(xiàn)接口:服務(wù)端實(shí)現(xiàn)生成的接口方法,客戶(hù)端通過(guò)代理類(lèi)調(diào)用這些方法。
- 綁定服務(wù):客戶(hù)端通過(guò) bindService() 將服務(wù)綁定到自己的進(jìn)程,從而可以通過(guò) AIDL 接口調(diào)用服務(wù)端的功能。
AIDL使用
通常一個(gè)apk就是一個(gè)進(jìn)程,要實(shí)現(xiàn)進(jìn)程間通信需要兩個(gè)進(jìn)程,一個(gè)作為服務(wù)端,一個(gè)作為客戶(hù)端,服務(wù)端來(lái)定義AIDL接口,寫(xiě)接口實(shí)現(xiàn),客戶(hù)端可以調(diào)用服務(wù)端的AIDL接口實(shí)現(xiàn)功能。
注意:實(shí)現(xiàn)AIDL需要系統(tǒng)權(quán)限,準(zhǔn)備工作需要在兩個(gè)進(jìn)程中都添加系統(tǒng)權(quán)限和系統(tǒng)簽名。
這里創(chuàng)建一個(gè)Project工程,其中的app包名設(shè)置為com.example.aidlserver,作為AIDL的服務(wù)端,然后新建一個(gè)module作為AIDL的客戶(hù)端,包名設(shè)置為com.example.aidlclient
AIDL服務(wù)端
1. 定義AIDL服務(wù)接口
先在com.example.aidlserver中創(chuàng)建AIDL接口,選中包名右鍵新建AIDL,接口名為IAidlServer。


在IAidlServer.aidl中增加add()和minus()兩個(gè)功能接口。
<app/main/aidl/com.example.aidlserver/IAidlServer.aidl>
interface IAidlServer {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
int add(int num1, int num2);
int minus(int num1, int num2);
}
定義好AIDL接口后先編譯一遍,編譯之后Android會(huì)自動(dòng)生成AIDL的服務(wù)接口,其中實(shí)現(xiàn)了stub、proxy的class,以及TRANSACTION的code,用來(lái)通信處理。

2. 實(shí)現(xiàn)AIDL服務(wù)接口
在com.example.aidlserver中創(chuàng)建Service服務(wù)類(lèi),實(shí)現(xiàn)AIDL中的功能接口。
<app/main/java/com.example.aidlserver/AidlServer.java>
public class AidlServer extends Service {
private static final String TAG = "=== AidlServer ===";
// 服務(wù)實(shí)體
private final IAidlServer.Stub mStub = new IAidlServer.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
Log.d(TAG, "basicTypes ");
}
@Override
public int add(int num1, int num2) throws RemoteException {
int sum = num1 + num2;
Log.d(TAG, "add sum = " + sum);
return sum;
}
@Override
public int minus(int num1, int num2) throws RemoteException {
int differ = num1 - num2;
Log.d(TAG, "minus differ = " + differ);
return differ;
}
};
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate ");
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onStart ");
return mStub;
}
}
3. 靜態(tài)注冊(cè)Service
在A(yíng)ndroidManifest.xml中靜態(tài)注冊(cè)AIDL的實(shí)現(xiàn)類(lèi),將Service對(duì)外暴露,這樣客戶(hù)端才能訪(fǎng)問(wèn)。
<app/main/AndroidManifest.xml>
<service android:name=".AidlServer"
android:enabled="true"
android:exported="true">
<!-- enable:ture設(shè)置可用 exported:ture對(duì)外暴露 -->
<intent-filter>
<action android:name="com.example.aidlserver.aidlserver"/>
</intent-filter>
</service>
AIDL客戶(hù)端
1. 復(fù)制服務(wù)端的AIDL服務(wù)接口
把服務(wù)端的AIDL以及包目錄完整的拷貝到客戶(hù)端的mian目錄下,讓Client和Server的服務(wù)對(duì)象對(duì)等。

AIDL接口復(fù)制到客戶(hù)端之后編輯aidlclient模塊,在客戶(hù)端的build中生成服務(wù)接口。

2. 在客戶(hù)端綁定服務(wù)使用接口
首先在客戶(hù)端的MainActivity頁(yè)面中添加兩個(gè)按鈕,分別用來(lái)觸發(fā)實(shí)現(xiàn)add和minus功能。
然后在MainActivity.java中調(diào)用AIDL接口實(shí)現(xiàn)功能。
(1)綁定AIDL服務(wù)。
(2)調(diào)用接口。
(3)解綁AIDL服務(wù)。
<aidl/main/java/com.example.aidlserver/MainActivity.java>
public class MainActivity extends AppCompatActivity {
private static final String TAG = "=== AidlClient ===";
private IAidlServer aidlServer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
// 綁定 AidlService
Intent intent = new Intent();
intent.setAction("com.example.aidlserver.aidlserver");
intent.setPackage("com.example.aidlserver"); // server's package name
boolean isBound = bindService(intent, connection, BIND_AUTO_CREATE);
Log.d(TAG, "綁定服務(wù) bindService result: " + isBound);
initView();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 解綁 AidlService
unbindService(connection);
Log.d(TAG, "解綁服務(wù) unbindService finished !");
}
private void initView(){
// add
findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "add onClick : " + (aidlServer == null));
if (aidlServer != null) {
try {
int sum = aidlServer.add(12, 34);
Log.d(TAG, "sum = " + sum);
Toast.makeText(MainActivity.this, String.valueOf(sum), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "AidlServer.add error : " + e);
}
}
}
});
// minus
findViewById(R.id.minus).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "differ onClick : " + (aidlServer == null));
if (aidlServer != null) {
try {
int differ = aidlServer.minus(34, 12);
Log.d(TAG, "differ = " + differ);
Toast.makeText(MainActivity.this, String.valueOf(differ), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "aidlService.minus error : " + e);
}
}
}
});
}
private final ServiceConnection connection = new ServiceConnection() {
// 綁定服務(wù)成功
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
// 接受到了遠(yuǎn)程的服務(wù)
Log.d(TAG, "onServiceConnected!");
aidlServer = IAidlServer.Stub.asInterface(service);
}
// 解綁服務(wù)
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.d(TAG, "onServiceDisconnected!");
// 回收資源
aidlServer = null;
}
};
}
先運(yùn)行服務(wù)端,再運(yùn)行客戶(hù)端,點(diǎn)擊客戶(hù)端的按鈕就可以實(shí)現(xiàn)AIDL的接口功能了。