Binder是android系統(tǒng)特有IPC方式,安卓平臺中的各種服務(wù)交互基本都是Binder機制實現(xiàn)律胀,理解和掌握Binder機制的實現(xiàn)原理可有效提升軟件性能優(yōu)化點专钉,同時Binder機制的應(yīng)用也是動態(tài)代理方式實現(xiàn)插件化基礎(chǔ)。
安卓插件化學(xué)習(xí) Binder機制原理分析
網(wǎng)上雖然已有很多Binder類似的優(yōu)秀分析累铅,本文處于自我學(xué)習(xí)目的跃须,把我學(xué)理解和認(rèn)識的東西記錄一下。
Binder屬于android平臺特有的IPC通道娃兽,也是進(jìn)程間數(shù)據(jù)交互的核心內(nèi)容菇民。
安卓平臺IPC方式總的來說有5種:1、文件操作投储;2第练、Messenger;3玛荞、Provider; 4娇掏、AIDL;5勋眯、Socket婴梧。
這五種方式中,2客蹋、3塞蹭、4的實現(xiàn)都用到了Binder機制,這里主要以AIDL的使用講解Binder讶坯。
Binder設(shè)計結(jié)構(gòu)理解
1番电、通信進(jìn)程兩端兩個重要對象:一個是本地端的Proxy遠(yuǎn)程引用對象,一個是遠(yuǎn)程端的Stub實體對象
2辆琅、client端Proxy對象可以根據(jù)所定義的繼承IInterface接口的相關(guān)約定方法來操作server端Stub實體類漱办。
3、Android中在使用系統(tǒng)服務(wù)的時候通過getSystemService方法獲取到的其實都是Stub把遠(yuǎn)端的Binder轉(zhuǎn)化的對象婉烟,因為系統(tǒng)服務(wù)都是在system_server進(jìn)程中娩井,所以肯定是跨進(jìn)程獲取對象的,那么這個Binder對象其實就是上面的Proxy對象
4隅很、除client和Proxy進(jìn)程外撞牢,還存在者一個serverManager所在的進(jìn)程(0號引用獲嚷誓搿),用來存儲proxy引用與stub實體的對應(yīng)關(guān)系屋彪。
5所宰、簡單理解:ProxyBinder的transact方法調(diào)用后會同步(可異步)調(diào)用到Stub類的onTransact.這中間進(jìn)程間數(shù)據(jù)的一次拷貝都是在系統(tǒng)空間的Binder驅(qū)動中完成。
Binder的使用
Binder的使用基本存在與多進(jìn)程的App中畜挥,大家工作的項目中很可能甚少接觸底層數(shù)據(jù)在進(jìn)程間的傳遞仔粥,特別是業(yè)務(wù)需求多的應(yīng)用。然后本地工具類應(yīng)用如衛(wèi)士類的產(chǎn)品研發(fā)會很經(jīng)常的應(yīng)用到Binder蟹但,并且會在不同的場合自定義Binder的數(shù)據(jù)傳遞方式躯泰,這里也很感謝之前工作項目“手機衛(wèi)士”的實際應(yīng)用機會。
標(biāo)準(zhǔn)AIDL使用Binder
AIDL( Android Interface definition language)安卓進(jìn)程間通信接口語言华糖,我們可以通過這種方式定義接口麦向,完成兩個或多個進(jìn)程間的信息傳遞。
1. 定義.aidl 接口文件
首先要定義進(jìn)程間需要完成什么操作客叉,傳遞什么數(shù)據(jù)诵竭,根據(jù)需求定義方法接口。
package com.canking.binder.aidl;
import com.canking.binder.aidl.Data;
interface AIDLService {
void setData(Data cb);
}
2. 編譯項目生產(chǎn)java文件
定義完.aidl 文件有兼搏,通過as build項目后卵慰,IDE會幫我們生產(chǎn)對應(yīng)的java文件在gen目錄下。
public interface AIDLService extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.canking.binder.aidl.AIDLService {
private static final java.lang.String DESCRIPTOR = "com.canking.binder.aidl.AIDLService";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.canking.binder.aidl.AIDLService,
* generating a proxy if needed.
*/
public static com.canking.binder.aidl.AIDLService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.canking.binder.aidl.AIDLService))) {
return ((com.canking.binder.aidl.AIDLService) iin);
}
return new com.canking.binder.aidl.AIDLService.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_onCallback: {
data.enforceInterface(DESCRIPTOR);
android.os.Bundle _arg0;
if ((0 != data.readInt())) {
_arg0 = android.os.Bundle.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
android.os.Bundle _result = this.setData(_arg0);
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.canking.binder.aidl.AIDLService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public android.os.Bundle onCallback(android.os.Bundle extra) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.os.Bundle _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((extra != null)) {
_data.writeInt(1);
extra.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_onCallback, _data, _reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
_result = android.os.Bundle.CREATOR.createFromParcel(_reply);
} else {
_result = null;
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_onCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public android.os.Bundle setData(android.os.Bundle extra) throws android.os.RemoteException;
}
3. 定義遠(yuǎn)端實體對象
public class AIDLServiceImpl extends AIDLService.Stub {
@Override
public boolean setData() {
doSomeThing();
return true;
}
}
@Override
public IBinder onBind(Intent intent) {
return AIDLServiceImpl;
}
繼承Stub類實現(xiàn)方法佛呻,并且通過Service的onBind()或Provider的call()提供接口返回給client端裳朋。
當(dāng)然,也可以不定義aidl文件吓著,自己定義Stub類及proxy類鲤嫡,好處是按照自己的需求自定義Stub的達(dá)到自定義Parcel讀取方式及實現(xiàn)邏輯來解決一些業(yè)務(wù)需求問題,比如復(fù)雜繼承類的傳遞夜矗。
4. Client端獲取遠(yuǎn)端ProxyBinder
3中定義好Binder對象后泛范,這個Binder就可以跨進(jìn)程調(diào)用類,獲取這個遠(yuǎn)端binder引用的方法有很多紊撕,利用Service啟動方法中的ServiceConnection來返回onBinder里的對象∩耐唬或者用Provider的call根據(jù)標(biāo)記返回指定Binder對象(封裝在Bundle中)对扶。
安卓源碼ServiceManager分析
ServiceManager是一個全局的manager、調(diào)用了Jni函數(shù)惭缰,實現(xiàn)addServicew getService checkService listService等函數(shù)浪南,
Server進(jìn)程先注冊一些service到SercviceManager中。
Client想獲得一些service漱受,就要到Service中去獲取該Service络凿。
這樣,Server和Client之間就可以進(jìn)行通訊了,
Server和Client之間的通訊都是通過Binder進(jìn)行的絮记。
——————
歡迎轉(zhuǎn)載摔踱,請標(biāo)明出處:常興E站 www.canking.win