Binder中的asInterface解析,queryLocalInterface解析

轉(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)下回乳怎。彩郊。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蚪缀,一起剝皮案震驚了整個(gè)濱河市秫逝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌询枚,老刑警劉巖违帆,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異金蜀,居然都是意外死亡刷后,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)渊抄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)尝胆,“玉大人,你說(shuō)我怎么就攤上這事护桦『危” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)贪染。 經(jīng)常有香客問(wèn)我缓呛,道長(zhǎng),這世上最難降的妖魔是什么杭隙? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任哟绊,我火速辦了婚禮,結(jié)果婚禮上寺渗,老公的妹妹穿的比我還像新娘匿情。我一直安慰自己,他們只是感情好信殊,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布炬称。 她就那樣靜靜地躺著,像睡著了一般涡拘。 火紅的嫁衣襯著肌膚如雪玲躯。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天鳄乏,我揣著相機(jī)與錄音跷车,去河邊找鬼。 笑死橱野,一個(gè)胖子當(dāng)著我的面吹牛朽缴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播水援,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼密强,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蜗元?” 一聲冷哼從身側(cè)響起或渤,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奕扣,沒(méi)想到半個(gè)月后薪鹦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惯豆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年池磁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片循帐。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡框仔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拄养,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布瘪匿,位于F島的核電站跛梗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏棋弥。R本人自食惡果不足惜核偿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望顽染。 院中可真熱鬧漾岳,春花似錦、人聲如沸粉寞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)唧垦。三九已至捅儒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間振亮,已是汗流浹背巧还。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坊秸,地道東北人麸祷。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像褒搔,于是被迫代替她去往敵國(guó)和親阶牍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345