標籤:android驅動 binder
Binder用於完成處理序間通訊(IPC),即把多個進程“別”在一起,從線程的角度來講,Binder驅動代碼運行在核心態,用戶端程式調用Binder是通過系統調用完成的。Binder是一種架構,這種架構提供了服務端介面、Binder驅動、用戶端介面三個模組。
重載onTransactO函數的主要內容是把onTmnSact()函數的參數轉換為服務函數的參數,而onTransact()函數的參數來源是用戶端調用transact()函數時輸入的。
任意一個服務端Binder對象被建立時,同時會在Binder驅動中建立一個
mRemote對象,該對象的類型也是Binder類。用戶端要訪問遠程服務時,都是通過mRemote對象。用戶端似乎是直接調用遠程服務對應的Binder,而事實上則是通過Binder驅動進行了中轉。即存在兩個Binder對象,一個是服務端的Binder對象,另一個則是Binder驅動中的Binder對象,所不同的是Binder驅動中的對象不會再額外產生一個線程。
服務端設計
Public class MusicPlayService extends Binder{/*** MusicPlayServicemusicPlayService=newMusicPlayService();會開啟一個新線程* code:是用戶端與服務端約定的,代表變數存取的編號(多個變數公用一個編號)* data:用戶端資料存放* replay:服務端返回的資料存放* flag:IPC調用的模式* 一種是雙向,用常量0表示,其含義是服務端執行完指定服務後會返回一定的資料;* 一種是單向,用常量1表示,其含義是不返回任何資料。*/@OverrideProtected boolean onTransact(int code,Parcel data,Parcel reply,int flags) throws RemoteException{switch(code){case1000://為了某種校正,它與用戶端的writeInterfaceToken()對應data.enforceInterface("MusicPlayService");String arg=data.readString();String arg1 = data.readString();break;case2000:data.enforceInterface("MusicPlayService");arg=data.readString();break;}returnsuper.onTransact(code,data,reply,flags);}publicvoidstart(){}publicvoidstop(){} }
Binder驅動
當建立一個Binder對象時,服務端進程內部建立一個Binder對象,Binder驅動中也會建立一個Binder對象。如果從遠程擷取服務端的Binder,則只會返回Binder驅動中的Binder對象,而如果從服務端進程內部擷取Binder對象,則會擷取服務端本身的Binder對象。
用戶端設計
publicclassMusicPlayClient{
/**
* 兩個問題:
* 1、用戶端如何獲得服務端的Binder對象引用?
*為什麼使用Binder?為了提供一個全域服務,系統的任何應用程式都可以使用,解決方案就是用service服務
* 2、用戶端和服務端必須事先約定好兩件事情:服務端函數的參數在包裹中的順序、服務端不同函數的int型標識
*
*service是如何解決上述兩個問題
*第一個問題:
*用戶端通過binderService和startService來啟動服務
*bindService(service,conn,flags)和StartService(service)
*ServiceConnection{
*onServiceConnected(ComponentNamename,IBinderservice);
*}
*通過bind來綁定服務,如果service啟動成功,ActivityManagerService就會調用ActivityThread類中的ApplicationThread對象,調用的參數中會包含service的Binder引用,然後再ApplicationThread中回調bindService中的conn介面,用戶端可將其設為全域變數。
*第二個問題:
*Androidsdk中提供了aidl工具,可以把一個aidl檔案轉化成java類,其重載了transact和onTransact方法,統一了包裹存放和包裹讀取的參數
*Proxy:用戶端訪問服務端的代理,統一包裹參數寫入的順序
*Stub:由服務端使用
*當建立一個Binder對象時,服務端進程內部建立一個Binder對象,Binder驅動中也會建立一個Binder對象。如果從遠程擷取服務端的Binder,則只會返回Binder驅動中的Binder對象,而如果從服務端進程內部擷取Binder對象,則會擷取服務端本身的Binder對
*/
Public void sendPacket()throwsRemoteException{
IBinde rmRemote=null;
String arg="agr0";
Parcel data=Parcel.obtain();
Parcel reply=Parcel.obtain();
data.writeInterfaceToken("MusicPlayService");//標註遠程服務名稱
data.writeString(arg);
Int flags=0;
/**
*用戶端線程進入Binder驅動,Binder驅動就會掛起當前線程,並向遠程服務發送一個訊息,
*訊息中包含了用戶端傳進來的包裹。服務端拿到包裹後,會對包裹進行拆解,然後執行指定的服務函數,
*執行完畢後,再把執行結果放入用戶端提供的reply包裹中。然後服務端向Binder驅動發送一個notify的訊息,
*從而使得用戶端線程從Binder驅動代碼區返回到用戶端代碼區。
*/
mRemote.transact(1,data,reply,flags);
IBinderbinder=reply.readStrongBinder();
data.recycle();
reply.recycle();
}
}
android Binder講解