AIDL是Android跨進(jìn)程間的一種非常重要的IPC通信機(jī)制,今天我們將來詳細(xì)講述如何不同app之間如何進(jìn)行AIDL IPC通信。
1. 創(chuàng)建service端工程
由于Android Studio剛剛發(fā)布3.0版本,所以我們就用它來嘗個鮮。
可用原來android studio 版本點(diǎn)擊菜單Help-->Check for Updates... 之后Android studio就會自動下載更新包進(jìn)行升級,可惜我升級半天,升級期間報幾個沖突,結(jié)果升級失敗,自動回滾,導(dǎo)致原來的AS2.3.3無法啟動,無奈只能直接下載AS3.0手動安裝。
a) 創(chuàng)建AIDL Service端工程AidlServerDemo
創(chuàng)建完后工程項(xiàng)目結(jié)構(gòu)如圖1所示:
b) 創(chuàng)建AIDL文件
右擊Java目錄 New --> AIDL --> AIDL File
輸入接口名稱IOnroad
此時會在與java同一目錄下生成aidl文件夾及對應(yīng)的包名和aidl文件
如圖2所示:
AS自動幫我們生成了一個基本類型的aidl接口
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
但我們并不打算用它,我們自己來定義一個簡單的基本類型
String sayHello(String name, int age);
點(diǎn)擊菜單Build-->Make Project,即可在對應(yīng)目錄下生成Java接口文件,如圖3所示:
c) 創(chuàng)建一個service來實(shí)現(xiàn)這個接口類
public class OnroadService extends Service {
public OnroadService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
我們創(chuàng)建了一個OnroadService, AS自動幫我們生成了一個構(gòu)造函數(shù)及實(shí)現(xiàn)了onBind接口,由于該接口未綁定相應(yīng)的binder,所以暫時返回UnsupportedOperationException("Not yet implemented")異常。
接下來我們將在這個service里實(shí)現(xiàn)我們的aidl接口, 并在onBind方法里返回mBinder給調(diào)用者,調(diào)用者就可以透過mBinder調(diào)用我們的aidl接口了。
private IOnroad.Stub mBinder = new IOnroad.Stub() {
@Override
public String sayHello(String name, int age) throws RemoteException {
String str = "Hello " + name + ", your age is " + age;
Log.d(TAG, str);
return str;
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mBinder;
}
d) 在AndroidManifest.xml注冊該service
<service
android:name=".service.OnroadService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="tech.onroad.aidlservicedemo.onroadservice"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
至此,整個service端已創(chuàng)建完成。
2. 創(chuàng)建Client端工程
a) 創(chuàng)建AIDL Client端工程AidlClientDemo
b) 復(fù)制service端的aidl文件及aidl對應(yīng)的java文件到客戶端
為了能在Client端掉用service端的接口,必須將service端的aidl文件及AS自動生成的aidl對應(yīng)的java文件復(fù)制到該工程,且保持包名不變。如圖4所示:
c) 創(chuàng)建ServiceConnection類
用于綁定Service, 若綁定成功,會回調(diào)onServiceConnected()方法,我們可以復(fù)寫該方法,獲取該service的ibinder接口; 若Service斷開連接,則必須銷毀binder實(shí)例,否則會造成內(nèi)存泄漏。
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mIOnroad = IOnroad.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mIOnroad = null;
}
};
d) 綁定服務(wù)
為了方便,我們讓Activity啟動的時候就去綁定服務(wù)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent mServiceIntent = new Intent();
mServiceIntent.setAction("tech.onroad.aidlservicedemo.onroadservice");
mServiceIntent.setPackage("tech.onroad.aidlserverdemo");
bindService(mServiceIntent, conn, Context.BIND_AUTO_CREATE);
}
setAction里的參數(shù)tech.onroad.aidlserverdemo就是我們Service在AndroidManifest.xml注冊的action, setPackage需指定service所在的包名,因?yàn)樵贏ndroid 5.0以后,android已不再支持隱式Intent Service,所以必須指定service所在的包名。這樣Client端綁定Service就已經(jīng)完成。
e) 調(diào)用aidl接口
接下來我們嘗試調(diào)用一下service端的aidl接口,看能否調(diào)用成功。
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mIOnroad = IOnroad.Stub.asInterface(iBinder);
try {
String svcRet = mIOnroad.sayHello("dflw", 20);
Log.d("Client", "Service return " + svcRet);
} catch (RemoteException e) {
e.printStackTrace();
}
}
為了圖方便,我直接綁定成功后的回調(diào)接口onServiceConnected()調(diào)用service的AIDL接口。
3. 測試
將AidlServerDemo及AidlClientDemo的apk裝載到Android設(shè)備或者模擬器上,
11-09 05:52:24.622 5439-5452/tech.onroad.aidlserverdemo D/OnroadService: Hello Liting, your age is 20
11-09 05:52:24.622 6662-6662/tech.onroad.aidlclientdemo D/Client: Service return Hello Liting, your age is 20
由上面的log可知,Client端已能正確調(diào)用Service端的接口,并成功將參數(shù)傳遞給Service端,且Service端也能將結(jié)果正確返回給Client.
完整代碼可到我的github下載:
https://github.com/onroadtech/AidlDemo
更多博文可訪問我的個人網(wǎng)站:www.onroad.tech
歡迎指定,共同進(jìn)步,指定郵箱:onroad_tech@163.com