? ? ?AIDL(android進口描述語言)是一種借口描述語言什燕,通常應用與進程間通信。編譯根據(jù)AIDL文件生成一個系列對應的Java類,通過預先定義的接口以及Binder機制達到進程間通信的目的萝快。其實就是一個接口锻霎,客戶端(調用者)通過bindService來與遠程服務端建立一個連接,在建立連接時會返回一個IBinder對象揪漩,該對象是服務器端Binder的BinderProxy(其實就是一個代理替身)旋恼,客戶端通過asInterface函數(shù)將該BinderProxy對象包裝成本地的Proxy,并對遠程的服務端的BinderProxy對象賦值給Proxy類的mRemote字段奄容,就是通過mRemote執(zhí)行遠程函數(shù)調用冰更。
使用AIDL實現(xiàn)IPC
使用AIDL實現(xiàn)IPC服務的步驟是:
1.創(chuàng)建.aidl文件-該文件(YourInterface.aidl)定義了客戶端可用的方法和數(shù)據(jù)的接口。
2.在makefile文件中加入.aidl文件-(Eclipse中的ADT插件提供管理功能)Android包括名為AIDL的編譯器昂勒,位于tools/文件夾蜀细。
3.實現(xiàn)接口-AIDL編譯器從AIDL接口文件中利用Java語言創(chuàng)建接口,該接口有一個繼承的命名為Stub的內部抽象類(并且實現(xiàn)了一些IPC調用的附加方法)叁怪,要做的就是創(chuàng)建一個繼承于YourInterface.Stub的類并且實現(xiàn)在.aidl文件中聲明的方法审葬。
4.向客戶端公開接口-如果是編寫服務,應該繼承Service并且重載Service.onBind(Intent)以返回實現(xiàn)了接口的對象實例
創(chuàng)建.aidl文件
AIDL使用簡單的語法來聲明接口奕谭,描述其方法以及方法的參數(shù)和返回值涣觉。這些參數(shù)和返回值可以是任何類型,甚至是其他AIDL生成的接口血柳。重要的是必須導入所有非內置類型官册,哪怕是這些類型是在與接口相同的包中。下面是AIDL能支持的數(shù)據(jù)類型:
1.Java編程語言的主要類型(int, boolean等)—不需要import語句难捌。
2.以下的類(不需要import語句):
String
List-列表中的所有元素必須是在此列出的類型膝宁,包括其他AIDL生成的接口和可打包類型。List可以像一般的類(例如List)那樣使用根吁,另一邊接收的具體類一般是一個ArrayList员淫,這些方法會使用List接口。
Map- Map中的所有元素必須是在此列出的類型击敌,包括其他AIDL生成的接口和可打包類型介返。一般的maps(例如Map)不被支持,另一邊接收的具體類一般是一個HashMap沃斤,這些方法會使用Map接口圣蝎。
CharSequence-該類是被TextView和其他控件對象使用的字符序列。
3.通常引引用方式傳遞的其他AIDL生成的接口衡瓶,必須要import語句聲明
4.實現(xiàn)了Parcelable protocol以及按值傳遞的自定義類徘公,必須要import語句聲明。
實例:
首先創(chuàng)建一個AIDL文件
package com.example.aidl;
interface?IDownload {
viod download(String ?path)哮针;
}
此時在工程里面Rebuild一下就會生成一個IDownload.java的文件生成关面,該類是根據(jù)IDownload.aidl文件坦袍;
其次 IDownloadService.java 類中的源碼如下:
public class IDownloadService extends Service {
private String[] URL= {"url1","url2","url3"};
private IBinder mIBinder=new DownloadBinder();
@Override
public?IBinder?onBind(Intent?intent)?{
//?TODO?Auto-generated?method?stub
return?mIBinder;
}
private class DownloadBinder extends IDownload.Stub{
@Override
public void downloade(string path) throws RemoteException {
? ? ? Log.i("DownloadBinder", path);
? ? ? ?}
}
}
從上述代碼中我們可以看出,實際上主要負責完成事務的是Stub的IDownload.Stub類缭裆,Service只是通過中間介質键闺。
不要忘記注冊一下Service;
然后運行調用端(Server端)澈驼,并且在客戶端完成Server的代碼辛燥。客戶端Activity代碼如下:
public class AIDLDemoActivity extends Activity {
private IDownload?downloadService;
/**?Called?when?the?activity?is?first?created.?*/
@Override
public?void?onCreate(Bundle?savedInstanceState)?{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent service=new Intent("com.example.aidl.downloadservice");
bindService(service,?conn,?BIND_AUTO_CREATE);
}
@Override
protected?void?onDestroy()?{
unbindService(conn);
super.onDestroy();
}
private ServiceConnection conn =new ServiceConnection() {
@Override
public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{
//?TODO?Auto-generated?method?stub
downloadService = IDownload.Stub.asInterface(service);
try{
downloadService.download(url);
}cache (RemoteException e){
e.printStackTrace();
}
}
@Override
public?void?onServiceDisconnected(ComponentName?name)?{
//?TODO?Auto-generated?method?stub
downloadService =null;
}
}
}
此時運行程序時會向Server端發(fā)起連接Service請求缝其,在連接后會將Binder對象轉換為IDownload對象挎塌,然后調用download()方法。此時download()實際上調用Server端的DownloadBinder類的實現(xiàn)内边。
到此榴都,我們就可以了解了 Android應用中如何通過AIDL機制實現(xiàn)兩個進程的通訊。但是這些只是為了方便開發(fā)者很方便的去調用和完成開發(fā)漠其;現(xiàn)在我們看看核心是通過AIDL文件上傳的Stub類以及背后的Binder機制嘴高。
有興趣的可以看一下生成的IDownload.java類,Stub類就是給文件的內部類和屎,其內部實現(xiàn)如何轉換通信兩端的對象以及方法拴驮。
public interface IDownload extends android.os.IInterface{
public static abstract class Stub extends android.os.Binder implements com.example.aidl.downloadservice.IDownloadBinder{
.............
public Stub(){
this.attachInterface(this,DESCRIPTOR);}
}
...............
}
其實AIDL內部實現(xiàn)機制很復雜,其中服務端柴信、客戶端之間還需要底層通信機制進行實現(xiàn)套啤,這就是C部分,通過底層的機制進行客戶端和服務端的多次握手随常。
第一次使用簡書潜沦,所以文章中容易出現(xiàn)錯誤,如有錯誤歡迎拍鉆绪氛。