AIDL是Android跨進(jìn)程間的一種非常重要的IPC通信機(jī)制,今天我們將來詳細(xì)講述如何不同app之間如何進(jìn)行AIDL IPC通信。
前期基礎(chǔ)知識儲備
-
IPC定義:
IPC是intent-Process Communication的縮寫,含義為進(jìn)程間通信或者跨進(jìn)程通信,是指兩個進(jìn)程之間進(jìn)行數(shù)據(jù)交換的過程。IPC不是Android所獨(dú)有的,任何一個操作系統(tǒng)都需要有相應(yīng)的IPC機(jī)制,比如Windows上可以通過剪貼板、管道和郵槽等來進(jìn)行進(jìn)程間通信,而Linux上可以通過命名共享內(nèi)容、信號量等來進(jìn)行線程間通信。對于Android來說,它也有自己的進(jìn)程間通信方式,Android建構(gòu)在Linux基礎(chǔ)上,繼承了一部分Linux的通信方式,同時Android也有自己特有的通信方式。
創(chuàng)建應(yīng)用工程

-
創(chuàng)建AIDL Service端工程model
APP -
創(chuàng)建AIDL文件
右擊Java目錄 New --> AIDL --> AIDL File
輸入接口名稱IMyAidlInterface
此時會在與java同一目錄下生成aidl文件夾及對應(yīng)的包名和aidl文件

AS自動幫我們生成了一個基本類型的aidl接口
interface IMyAidlInterface{
/**
* 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);
}
但我們并不打算用它,我們自己來定義一個簡單的基本類型IOnroad
interface IOnroad {
/**
* 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);
void sayHello(String name,int age);
}
點(diǎn)擊菜單Build-->Make Project,即可在對應(yīng)目錄下生成Java接口文件,如圖所示:

-
創(chuàng)建一個service來實(shí)現(xiàn)這個接口類
我們創(chuàng)建了一個OnroadService, 并在onBind方法里返回mBinder給調(diào)用者,調(diào)用者就可以透過mBinder調(diào)用我們的aidl接口了。
public class OnroadService extends Service {
public OnroadService() {
}
private String TAG = "OnroadService";
private IOnroad.Stub binder = new IOnroad.Stub() {
@Override
public void sayHello(String name, int age) throws RemoteException {
String text = "sayHello: --->name" + name + "age:" + age;
Log.i(TAG, text);
//Toast.makeText(OnroadService.this, text, Toast.LENGTH_SHORT).show();
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
-
在AndroidManifest.xml注冊該service
<service
android:name=".service.OnroadService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.lypeer.aidl" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
創(chuàng)建Client端應(yīng)用
-
創(chuàng)建AIDL Client端工程工程model

-
復(fù)制service端的aidl文件及aidl對應(yīng)的java文件到客戶端
為了能在Client端掉用service端的接口,必須將service端的aidl文件及AS自動生成的aidl對應(yīng)的java文件復(fù)制到該工程,且保持包名不變。

-
創(chuàng)建ServiceConnection類
用于綁定Service, 若綁定成功,會回調(diào)onServiceConnected()方法,我們可以復(fù)寫該方法,獲取該service的ibinder接口; 若Service斷開連接,則必須銷毀binder實(shí)例,否則會造成內(nèi)存泄漏。
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// IOnroad.Stub binder =
IOnroad onroad = IOnroad.Stub.asInterface(service);
try {
// onroad.sayHello();
onroad.sayHello("哈嘍",100);
} catch (RemoteException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "有異常的情況!", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
-
綁定服務(wù)
為了方便,我們讓Activity啟動的時候就去綁定服務(wù)
setAction里的參數(shù)tech.onroad.aidlserverdemo就是我們Service在AndroidManifest.xml注冊的action, setPackage需指定service所在的包名,因?yàn)樵贏ndroid 5.0以后,android已不再支持隱式Intent Service,所以必須指定service所在的包名。這樣Client端綁定Service就已經(jīng)完成。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setAction("com.lypeer.aidl");
intent.setPackage("com.zxn.service");
bindService(intent,connection,BIND_AUTO_CREATE);
}
-
調(diào)用aidl接口
接下來我們嘗試調(diào)用一下service端的aidl接口,看能否調(diào)用成功。
測試
可以看到服務(wù)端從異步線程傳遞過來的數(shù)據(jù),日志輸出如下
--->name:say onClickage:1028Thread:Binder:5786_4