Aidl进程间通信详细介绍
目錄介紹
- 1.問題答疑
-
2.Aidl相關(guān)屬性介紹
- 2.1 AIDL所支持的數(shù)據(jù)類型
- 2.2 服務(wù)端和客戶端
- 2.3 AIDL的基本概念
-
3.實(shí)際開發(fā)中案例操作
- 3.1 aidl通信業(yè)務(wù)需求
- 3.2 操作步驟偽代碼
- 3.3 服務(wù)端操作步驟
- 3.4 客戶端操作步驟
- 3.5 測試
-
4.可能出現(xiàn)的問題
- 4.1 客戶端在子線程中發(fā)起通信訪問問題
- 4.2 什么情況下會(huì)導(dǎo)致遠(yuǎn)程調(diào)用失敗
- 4.3 設(shè)置aidl的權(quán)限,需要通過權(quán)限才能調(diào)用
-
5.部分源碼解析
- 5.1 服務(wù)端aidl編譯生成的java文件
- 5.2 客戶端綁定服務(wù)端service原理
關(guān)于aidl應(yīng)用案例
- https://github.com/yangchong211/YCAudioPlayer
關(guān)于鏈接
- 1.技術(shù)博客匯總
- 2.開源項(xiàng)目匯總
- 3.生活博客匯總
- 4.喜馬拉雅音頻匯總
- 5.其他匯總
1.問題答疑
- 1.1.0 AIDL所支持的數(shù)據(jù)類型有哪些?
- 1.1.1 提供給客戶端連接的service什么時(shí)候運(yùn)行?
- 1.1.2 Stub類是干什么用的呢?
- 1.1.3 如何解決遠(yuǎn)程調(diào)用失敗的問題?
2.Aidl相關(guān)屬性介紹
2.1 AIDL所支持的數(shù)據(jù)類型
-
在AIDL中,并非支持所有數(shù)據(jù)類型,他支持的數(shù)據(jù)類型如下所示:
- 基本數(shù)據(jù)類型(int、long、char、boolean、double、float、byte、short)
- String和CharSequence
- List:只支持ArrayList,并且里面的每個(gè)元素必須被AIDL支持
- Map: 只支持HashMap, 同樣的,里面的元素都必須被AIDL支持,包括key和value
- Parcelable:所有實(shí)現(xiàn)了Parcelable接口的對象
- AIDL: 所有的AIDL接口本身也可以在AIDL 文件中使用
2.2 服務(wù)端和客戶端
-
2.2.1 服務(wù)端
- 注意:服務(wù)端就是你要連接的進(jìn)程。服務(wù)端給客戶端一個(gè)Service,在這個(gè)Service中監(jiān)聽客戶端的連接請求,然后創(chuàng)建一個(gè)AIDL接口文件,里面是將要實(shí)現(xiàn)的方法,注意這個(gè)方法是暴露給客戶端的的。在Service中實(shí)現(xiàn)這個(gè)AIDL接口即可
-
2.2.2 客戶端
- 客戶端首先需要綁定服務(wù)端的Service,綁定成功后,將服務(wù)端返回的Binder對象轉(zhuǎn)換成AIDL接口所屬的類型,最后調(diào)用AIDL的方法就可以了。
2.3 AIDL的基本概念
- AIDL:Android Interface Definition Language,即Android接口定義語言;用于讓某個(gè)Service與多個(gè)應(yīng)用程序組件之間進(jìn)行跨進(jìn)程通信,從而可以實(shí)現(xiàn)多個(gè)應(yīng)用程序共享同一個(gè)Service的功能。
3.實(shí)際開發(fā)中案例操作
3.1 aidl通信業(yè)務(wù)需求
- aidl多進(jìn)程通信應(yīng)用——服務(wù)端:某app;客戶端:app調(diào)試工具。注意:aidl多進(jìn)程通信是指兩個(gè)獨(dú)立app之間的通信……
- 打開app調(diào)試工具,可以通過綁定服務(wù)端某app的service,獲取到公司app的信息,比如渠道,版本號,簽名,打包時(shí)間,token等屬性
- 通過app調(diào)試工具,可以通過aidl接口中的方法設(shè)置屬性,設(shè)置成功后,查看某app是否設(shè)置屬性成功
3.2 操作步驟偽代碼
-
3.2.1 服務(wù)端
- 步驟1:新建定義AIDL文件,并聲明該服務(wù)需要向客戶端提供的接口
- 補(bǔ)充,如果aidl中有對象,則需要?jiǎng)?chuàng)建對象,并且實(shí)現(xiàn)Parcelable
- 步驟2:在Service子類中實(shí)現(xiàn)AIDL中定義的接口方法,并定義生命周期的方法(onCreat、onBind()、blabla)
- 步驟3:在AndroidMainfest.xml中注冊服務(wù) & 聲明為遠(yuǎn)程服務(wù)
-
3.2.2 客戶端
- 步驟1:拷貝服務(wù)端的AIDL文件到目錄下
- 步驟2:使用Stub.asInterface接口獲取服務(wù)器的Binder,根據(jù)需要調(diào)用服務(wù)提供的接口方法
- 步驟3:通過Intent指定服務(wù)端的服務(wù)名稱和所在包,綁定遠(yuǎn)程Service
3.3 服務(wù)端操作步驟
-
3.3.1 創(chuàng)建一個(gè)aidl文件【注意:在main路徑下創(chuàng)建】
- 可以看到里面有一個(gè)AppInfo,注意這個(gè)類需要自己創(chuàng)建,并且手動(dòng)導(dǎo)包進(jìn)來。否則編譯時(shí)找不到……
-
3.3.2 創(chuàng)建一個(gè)AppInfo類,實(shí)現(xiàn)Parcelable接口
- 這個(gè)類就是需要用的實(shí)體類,因?yàn)槭强邕M(jìn)程,所以實(shí)現(xiàn)了Parcelable接口,這個(gè)是Android官方提供的,它里面主要是靠Parcel來傳遞數(shù)據(jù),Parcel內(nèi)部包裝了可序列化的數(shù)據(jù),能夠在Binder中自由傳輸數(shù)據(jù)。
- 注意:如果用到了自定義Parcelable對象,就需要?jiǎng)?chuàng)建一個(gè)同名的AIDL文件,包名要和實(shí)體類包名一致。我之前這個(gè)地方?jīng)]加,導(dǎo)致出現(xiàn)錯(cuò)誤!
- 如圖所示:
-
3.3.3 在Service子類中實(shí)現(xiàn)AIDL中定義的接口方法,并定義生命周期的方法(onCreat、onBind()等)
- 重寫的onBinde()方法中返回Binder對象,這個(gè)Binder對象指向IAdvertManager.Stub(),這個(gè)Stub類并非我們自己創(chuàng)建的,而是AIDL自動(dòng)生成的。系統(tǒng)會(huì)為每個(gè)AIDL接口在build/source/aidl下生成一個(gè)文件夾,它的名稱跟你命名的AIDL文件夾一樣,里面的類也一樣。
- 創(chuàng)建binder對象,在這個(gè)getAppInfo方法中,可以設(shè)置app基本信息,方便后期多進(jìn)程通信測試
-
3.3.4 在AndroidMainfest.xml中注冊服務(wù) & 聲明為遠(yuǎn)程服務(wù)
- 在清單文件注冊即可,需要設(shè)置action。這個(gè)在客戶端中綁定服務(wù)service需要用到!
3.4 客戶端操作步驟
-
3.4.1 拷貝服務(wù)端的AIDL文件到目錄下
- 注意:復(fù)制時(shí)不要改動(dòng)任何東西!
- 如圖所示:
-
3.4.2 通過Intent指定服務(wù)端的服務(wù)名稱和所在包,綁定遠(yuǎn)程Service
- 通過Intent指定服務(wù)端的服務(wù)名稱和所在包,進(jìn)行Service綁定;
- 創(chuàng)建ServiceConnection對象
-
3.4.3 使用Stub.asInterface接口獲取服務(wù)器的Binder,根據(jù)需要調(diào)用服務(wù)提供的接口方法
- 通過步驟3.4.2完成了跨進(jìn)程綁定服務(wù),接下來通過調(diào)用方法獲取到數(shù)據(jù)。這里可以調(diào)用getAppInfo方法獲取到服務(wù)端[app]的數(shù)據(jù)
3.5 測試
-
最后看看通過測試工具[客戶端]跨進(jìn)程獲取服務(wù)端app信息截圖
- 具體可以通過實(shí)際案例操作:后來發(fā)現(xiàn)跨進(jìn)程通信原來挺好玩的……項(xiàng)目地址:https://github.com/yangchong211/YCAudioPlayer
- 如圖所示:
4.可能出現(xiàn)的問題
4.1 客戶端在子線程中發(fā)起通信訪問問題
- 當(dāng)客戶端發(fā)起遠(yuǎn)程請求時(shí),客戶端會(huì)掛起,一直等到服務(wù)端處理完并返回?cái)?shù)據(jù),所以遠(yuǎn)程通信是很耗時(shí)的,所以不能在子線程發(fā)起訪問。由于服務(wù)端的Binder方法運(yùn)行在Binder線程池中,所以應(yīng)采取同步的方式去實(shí)現(xiàn),因?yàn)樗呀?jīng)運(yùn)行在一個(gè)線程中呢。
4.2 什么情況下會(huì)導(dǎo)致遠(yuǎn)程調(diào)用失敗
- Binder是會(huì)意外死亡的。如果服務(wù)端的進(jìn)程由于某種原因異常終止,會(huì)導(dǎo)致遠(yuǎn)程調(diào)用失敗,如果我們不知道Binder連接已經(jīng)斷裂, 那么客戶端就會(huì)受到影響。不用擔(dān)心,Android貼心的為我們提供了連個(gè)配對的方法linkToDeath和unlinkToDeath,通過linkToDeath我們可以給Binder設(shè)置一個(gè)死亡代理,當(dāng)Binder死亡時(shí),我們就會(huì)收到通知。
4.3 設(shè)置aidl的權(quán)限,需要通過權(quán)限才能調(diào)用
<!--給aidl多進(jìn)程通信,服務(wù)加入權(quán)限驗(yàn)證功能--> <permission android:name="aidl.AppInfoService"android:protectionLevel="normal"/>//在AppInfoService服務(wù)中驗(yàn)證權(quán)限 @Nullable @Override public IBinder onBind(Intent intent) {LogUtils.i("AppInfoService--IBinder:");int check = checkCallingOrSelfPermission("aidl.AppInfoService");if(check == PackageManager.PERMISSION_DENIED){return null;}return binder; }5.部分源碼解析
5.1 服務(wù)端aidl編譯生成的java文件
- 5.1.1 首先找到aidl編譯生成的Java文件
-
5.1.2 分析生成的java文件
- 這個(gè)ICheckAppInfoManager.java就是系統(tǒng)為我們生成的相應(yīng)java文件,簡單說下這個(gè)類。它聲明了三個(gè)方法getAppInfo,setToken和setChannel,分明就是我們AIDL接口中的三個(gè)方法。同時(shí)他聲明了3個(gè)id用來標(biāo)識這幾個(gè)方法,id用于標(biāo)識在transact過程中客戶端請求的到底是哪個(gè)方法。接著就是我們的Stub,可以看到它是一個(gè)內(nèi)部類,他本質(zhì)上是一個(gè)Binder類。當(dāng)服務(wù)端和客戶端位于同一個(gè)進(jìn)程時(shí),方法調(diào)用不會(huì)走跨進(jìn)程的transact過程,當(dāng)兩者處于不同晉城市,方法調(diào)用走transact過程,這個(gè)邏輯由Stub的內(nèi)部代理類Proxy完成。
- 這個(gè)Stub對象之所以里面有我們AIDL的接口,正是因?yàn)楣俜教嫖覀冏龊昧?#xff0c;我們只要在這里具體實(shí)現(xiàn)就好了。
5.2 客戶端綁定服務(wù)端service原理
- 客戶端也非常簡單,首先我們連接到服務(wù)端Service,在連接成功時(shí),也就是onServiceConnected方法里,通過asInterface(service)方法可以將服務(wù)端的Binder對象轉(zhuǎn)換成客戶端所需的AIDL的接口的對象。這種轉(zhuǎn)換是區(qū)分進(jìn)程的,如果是同一進(jìn)程,那么此方法返回的就是Stub本身,否則返回的就是系統(tǒng)Stub.proxy對象。拿到接口對象之后,我們就能夠調(diào)用相應(yīng)方法進(jìn)行自己的處理
參考文章
- Android 進(jìn)階7:進(jìn)程通信之 AIDL 的使用:https://blog.csdn.net/u011240877/article/details/72765136
- Android中AIDL的使用詳解:https://www.jianshu.com/p/d1fac6ccee98
- Android Aidl的使用:https://blog.csdn.net/menglong0329/article/details/75127547
- 安卓中AIDL的使用:https://blog.csdn.net/qq_32006371/article/details/71255764
關(guān)于我的博客
- 我的個(gè)人站點(diǎn):www.yczbj.org,www.ycbjie.cn
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
- 簡書:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜馬拉雅聽書:http://www.ximalaya.com/zhubo/71989305/
- 開源中國:https://my.oschina.net/zbj1618/blog
- 泡在網(wǎng)上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 郵箱:yangchong211@163.com
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault頭條:https://segmentfault.com/u/xiangjianyu/articles
總結(jié)
以上是生活随笔為你收集整理的Aidl进程间通信详细介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 遍历目录下的文件每250M打包一个文件
- 下一篇: Java jdbc连接数据库 INSER