轉(zhuǎn):https://blog.csdn.net/weixin_30475039/article/details/98149213
在使用AIDL通信的時(shí)候某饰,在Stub類(lèi)中都會(huì)生成一個(gè)asInterface函數(shù)示损,以《Android開(kāi)發(fā)藝術(shù)探索》中的例子來(lái)分析,其生成的asInterface函數(shù)源碼為:
1/** 2? ? ? ? * Cast an IBinder object into an com.willhua.demoaidl.aidl.IBookManager 3? ? ? ? * interface, generating a proxy if needed. 4*/ 5publicstatic com.willhua.demoaidl.aidl.IBookManager asInterface( 6? ? ? ? ? ? ? ? android.os.IBinder obj) { 7if((obj ==null)) { 8returnnull; 9? ? ? ? ? ? }10android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);11if(((iin !=null) && (iininstanceof com.willhua.demoaidl.aidl.IBookManager))) {12return ((com.willhua.demoaidl.aidl.IBookManager) iin);13? ? ? ? ? ? }14returnnew com.willhua.demoaidl.aidl.IBookManager.Stub.Proxy(obj);15}
我們知道asInterface的作用是根據(jù)調(diào)用是否屬于同進(jìn)程而返回不同的實(shí)例對(duì)象翼岁,但是對(duì)于該過(guò)程是怎么進(jìn)行的悦析,返回的到底是什么東西寿桨,可能很多童鞋不是很清楚,就這個(gè)問(wèn)題分享一點(diǎn)我的理解她按。顯然牛隅,通過(guò)代碼可知炕柔,決定返回何種對(duì)象的關(guān)鍵在obj.queryLocalInterface(DESCRIPTOR)的返回結(jié)果。
下面我們通過(guò)實(shí)際DEMO來(lái)了解其過(guò)程媒佣。代碼基于《Android開(kāi)發(fā)藝術(shù)探索》中的例子匕累。
DEMO中有主要有兩個(gè)東西,一個(gè)就是MainActivity默伍,一個(gè)就是BookService欢嘿,MainActivity會(huì)去bind?BookService,而B(niǎo)ookService通過(guò)在Manifest中設(shè)置android:process而使之分別與MainActivity運(yùn)行在同進(jìn)程和異進(jìn)程也糊。
主要代碼:
publicclassBookServiceextends Service {
? ? privateBinder mBinder =new IBookManager.Stub() {
? ? ...
? ? };
? ? @Override
? ? public IBinder onBind(Intent intent) {
? ? ? ? // TODO Auto-generated method stubLOG("BookService onBind mBinder:" +mBinder.getClass().getName() + " Process:" + Process.myPid());
? ? ? ? return mBinder;
? ? }
}
publicclassMainActivityextends Activity{
? ? private IBookManager mService;
? ? private Button mQuery;
? ? private TextView mOutInfo;
? ? ...
? ? @Override
? ? protectedvoid onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? connectService();
? ? }
? ? privatevoid connectService(){
? ? ? ? Intent intent =newIntent(getApplicationContext(), BookService.class);
? ? ? ? bindService(intent, new ServiceConnection() {
? ? ? ? ? ? @Override
? ? ? ? ? ? publicvoid onServiceDisconnected(ComponentName name) {
? ? ? ? ? ? ? ? // TODO Auto-generated method stub? ? ? ? ? ? ? ?
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? publicvoid onServiceConnected(ComponentName name, IBinder service) {
? ? ? ? ? ? ? ? // TODO Auto-generated method stubLOG("onServiceConnected " + service);
? ? ? ? ? ? ? ? mService =IBookManager.Stub.asInterface(service);? ? ? ? ? ? }? ? ? ? }, BIND_AUTO_CREATE);? ? ? ? ? ? }? ? ...}
publicstaticabstractclassStubextendsandroid.os.Binderimplements? ? ? ? ? ? com.willhua.demoaidl.aidl.IBookManager {
? ? ? ? privatestaticfinaljava.lang.String DESCRIPTOR = "com.willhua.demoaidl.aidl.IBookManager";
? ? ? ? /** Construct the stub at attach it to the interface. */public Stub() {
? ? ? ? ? ? this.attachInterface(this, DESCRIPTOR);
? ? ? ? }
? ? ? ? /**? ? ? ? * Cast an IBinder object into an com.willhua.demoaidl.aidl.IBookManager
? ? ? ? * interface, generating a proxy if needed.
? ? ? ? */publicstatic com.willhua.demoaidl.aidl.IBookManager asInterface(
? ? ? ? ? ? ? ? android.os.IBinder obj) {
? ? ? ? ? ? if((obj ==null)) {
? ? ? ? ? ? ? ? returnnull;
? ? ? ? ? ? }
? ? ? ? ? ? android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
? ? ? ? ? ? if(((iin !=null) && (iininstanceof com.willhua.demoaidl.aidl.IBookManager))) {
? ? ? ? ? ? ? ? return ((com.willhua.demoaidl.aidl.IBookManager) iin);
? ? ? ? ? ? }
? ? ? ? ? ? returnnew com.willhua.demoaidl.aidl.IBookManager.Stub.Proxy(obj);
? ? ? ? }
...
}
androd.os.Binder部分源碼:
publicclassBinderimplements IBinder {
? ? //.../**? ? * Convenience method for associating a specific interface with the Binder.
? ? * After calling, queryLocalInterface() will be implemented for you
? ? * to return the given owner IInterface when the corresponding
? ? * descriptor is requested.
? ? */publicvoid attachInterface(IInterface owner, String descriptor) {
? ? ? ? mOwner = owner;
? ? ? ? mDescriptor = descriptor;
? ? }
? ? /**? ? * Use information supplied to attachInterface() to return the
? ? * associated IInterface if it matches the requested
? ? * descriptor.
? ? */public IInterface queryLocalInterface(String descriptor) {
? ? ? ? if (mDescriptor.equals(descriptor)) {
? ? ? ? ? ? return mOwner;
? ? ? ? }
? ? ? ? returnnull;
? ? }
? ? //...finalclassBinderProxyimplements IBinder {
? ? ? ? //...public IInterface queryLocalInterface(String descriptor) {
? ? ? ? returnnull;
? ? ? ? }
? ? ? ? //...? ? }
}
通過(guò)LOG炼蹦,我們發(fā)現(xiàn),在onServiceConnected函數(shù)中狸剃,如果MainActivity與BookService同進(jìn)程掐隐,則打印的log為:
如果MainActivity與BookService異進(jìn)程,及MainActivity跨進(jìn)程綁定BookService服務(wù)钞馁,則打印的log為:
先分析同進(jìn)程虑省,
在同進(jìn)程中,onServiceConnected接收得到的service對(duì)象的類(lèi)型為BookServices$1僧凰,我們知道$表示的是BookServices中的內(nèi)部類(lèi)探颈,而在BookServices的定義中,我們只在mBinder的初始化中定義了一個(gè)IBookManager.Stub()的子類(lèi)训措,即同進(jìn)程時(shí)伪节,在onServiceConnected接收到的是IBookManager.Stub()類(lèi)型。而IBookManager.Stub() extenders?android.os.Binder?implements?IBookManager绩鸣,其queryLocalInterface方法來(lái)源于超類(lèi)android.os.Binder怀大。對(duì)于方法中傳入的descriptor,通過(guò)asInterface的代碼可知就是Stub中定義的DESCRIPTOR全闷,而B(niǎo)inder中定義的mDescriptor叉寂,其賦值過(guò)程是在attachInterface函數(shù)中,而attachInterface函數(shù)是在Stub的構(gòu)造函數(shù)中被調(diào)用总珠,其調(diào)用為
this.attachInterface(this, DESCRIPTOR);
而在onServiceConnected中的調(diào)用為:
mService = IBookManager.Stub.asInterface(service);
注意sercice為IBookManager.Stub,從而我們可以知道勘纯,
if (mDescriptor.equals(descriptor))
判斷語(yǔ)句中的mDescriptor和descriptor都為IBookManager.Stub中定義的DESCRIPTOR局服,則queryLocalInterface返回的是mOwer。那么mOwer又是什么呢驳遵?細(xì)心的童鞋估計(jì)已經(jīng)知道答案淫奔,在Stub的構(gòu)造函數(shù)調(diào)用中attachInterface的時(shí)候,已經(jīng)給mOwer賦值堤结,且賦值為this唆迁,即該Stub對(duì)象本身鸭丛!再回去對(duì)照asInterface的邏輯,我們即可以得出結(jié)論:同進(jìn)程時(shí)唐责,調(diào)用asInterface返回的是Stub對(duì)象鳞溉,其實(shí)就是在onBind中返回的mBinder。
再來(lái)分析跨進(jìn)程調(diào)用的情形
由上面的log可知鼠哥,跨進(jìn)程調(diào)用時(shí),onSericeConnected中接收到的service為android.os.BinderProxy類(lèi)型朴恳,而上面的源碼已經(jīng)給出抄罕,BinderProxy為final類(lèi),且其queryLocalInterface方法直接返回的null于颖,結(jié)合asInterface的代碼邏輯呆贿,就知道它返回的為IBookManager.Stub.Proxy對(duì)象,得出結(jié)論:同進(jìn)程時(shí)森渐,調(diào)用asInterface返回的是Stub.Proxy對(duì)象榨崩。
至此,開(kāi)篇提到的問(wèn)題應(yīng)該已經(jīng)明了章母。但其實(shí)又引出了一個(gè)新的問(wèn)題:為什么跨進(jìn)程調(diào)時(shí)母蛛,在onServiceConnected中接收到的是os.BinderProxy,而同進(jìn)程調(diào)用時(shí)接收到的是IBookManager.Stub?
且聽(tīng)下回乳怎。彩郊。。