![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 添加系統(tǒng)服務(wù)的方法詳解_第1頁(yè)](http://file4.renrendoc.com/view/1e6661c662fac07fee9398b1bac703b3/1e6661c662fac07fee9398b1bac703b31.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 添加系統(tǒng)服務(wù)的方法詳解_第2頁(yè)](http://file4.renrendoc.com/view/1e6661c662fac07fee9398b1bac703b3/1e6661c662fac07fee9398b1bac703b32.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 添加系統(tǒng)服務(wù)的方法詳解_第3頁(yè)](http://file4.renrendoc.com/view/1e6661c662fac07fee9398b1bac703b3/1e6661c662fac07fee9398b1bac703b33.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 添加系統(tǒng)服務(wù)的方法詳解_第4頁(yè)](http://file4.renrendoc.com/view/1e6661c662fac07fee9398b1bac703b3/1e6661c662fac07fee9398b1bac703b34.gif)
![【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android 添加系統(tǒng)服務(wù)的方法詳解_第5頁(yè)](http://file4.renrendoc.com/view/1e6661c662fac07fee9398b1bac703b3/1e6661c662fac07fee9398b1bac703b35.gif)
下載本文檔
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android添加系統(tǒng)服務(wù)的方法詳解
一、前言
系統(tǒng)服務(wù)是Android中非常重要的一部分,像ActivityManagerService,PackageManagerService,WindowManagerService,這些系統(tǒng)服務(wù)都是Framework層的關(guān)鍵服務(wù),本篇文章主要講一下如何基于Android源碼添加一個(gè)系統(tǒng)服務(wù)的完整流程,除了添加基本系統(tǒng)服務(wù),其中還包含添加JNI部分代碼和App通過(guò)AIDL調(diào)用的演示Demo,調(diào)用包含App調(diào)用服務(wù)端,也包含服務(wù)端回調(diào)App,也就是完成一個(gè)簡(jiǎn)單的雙向通信.注:測(cè)試代碼基于Android7.1.1,其他Android版本都是大同小異.二、編寫(xiě)AIDL文件
添加服務(wù)首先是編寫(xiě)AIDL文件,AIDL文件路徑如下:frameworks/base/core/java/com/example/utils/
1.ISystemEvent.aidl內(nèi)容如下:
2.IEventCallback.aidl內(nèi)容如下
AIDL文件編寫(xiě),教程很多,我這里就不詳細(xì)說(shuō)明了,需要注意的是,由于我們要實(shí)現(xiàn)回調(diào)功能,所以必須寫(xiě)一個(gè)回調(diào)接口IEventCallback,另外AIDL文件中oneway關(guān)鍵字表明調(diào)用此函數(shù)不會(huì)阻塞當(dāng)前線程,調(diào)用端調(diào)用此函數(shù)會(huì)立即返回,接收端收到函數(shù)調(diào)用是在Binder線程池中的某個(gè)線程中.可以根據(jù)實(shí)際項(xiàng)目需求選擇是否需要加oneway關(guān)鍵字.AIDL只支持傳輸基本java類型數(shù)據(jù),要想傳遞自定義類,類需要實(shí)現(xiàn)Parcelable接口,另外,如果傳遞基本類型數(shù)組,需要指定inout關(guān)鍵字,比如
voidtest(inbyte[]input,outbyte[]output)
,用in還是out,只需要記住:數(shù)組如果作為參數(shù),通過(guò)調(diào)用端傳給被調(diào)端,則使用in,如果數(shù)組只是用來(lái)接受數(shù)據(jù),實(shí)際數(shù)據(jù)是由被調(diào)用端來(lái)填充的,則使用out,這里之所以沒(méi)有說(shuō)服務(wù)端和客戶端,是因?yàn)閕nout關(guān)鍵字用哪個(gè)和是服務(wù)端還是客戶端沒(méi)有聯(lián)系,遠(yuǎn)程調(diào)用和被調(diào)用更適合描述.文件寫(xiě)完后,添加到編譯的Android.mk中LOCAL_SRC_FILES后面:3.frameworks/base/Android.mk
編譯代碼,
編譯前需執(zhí)行makeupdate-api,更新接口,然后編譯代碼,確保AIDL編寫(xiě)沒(méi)有錯(cuò)誤,編譯后會(huì)生成對(duì)應(yīng)java文件,服務(wù)端要實(shí)現(xiàn)對(duì)應(yīng)接口.三、編寫(xiě)Manager類
我們可以看到,AndroidAPI中有很多Manager類,這些類一般都是某個(gè)系統(tǒng)服務(wù)的客戶端代理類,其實(shí)我們不寫(xiě)Manager類,只通過(guò)AIDL文件自動(dòng)生成的類,也可以完成功能,但封裝一下AIDL接口使用起來(lái)更方便,我們測(cè)試用的Manager類為SystemEventManager,代碼如下:
frameworks/base/core/java/com/example/utils/SystemEventManager.java代碼很簡(jiǎn)單,就封裝了下AIDL接口,定義了系統(tǒng)服務(wù)注冊(cè)時(shí)用的名字.構(gòu)造函數(shù)中的ISystemEvent參數(shù)在后面注冊(cè)Manager時(shí)候會(huì)通過(guò)Binder相關(guān)接口獲取.編譯代碼,確保沒(méi)有錯(cuò)誤,下面編寫(xiě)系統(tǒng)服務(wù).四、編寫(xiě)系統(tǒng)服務(wù)
路徑以及代碼如下:
frameworks/base/services/core/java/com/android/server/example/SystemEventService.java服務(wù)端繼承自ISystemEvent.Stub,實(shí)現(xiàn)對(duì)應(yīng)的三個(gè)方法即可,需要注意的是,由于有回調(diào)功能,所以要把注冊(cè)的IEventCallback加到鏈表里面,這里使用了RemoteCallbackList,之所以不能使用普通的List或者M(jìn)ap,原因是,跨進(jìn)程調(diào)用,App調(diào)用registerCallback和unregisterCallback時(shí),即便每次傳遞的都是同一個(gè)IEventCallback對(duì)象,但到服務(wù)端,經(jīng)過(guò)跨進(jìn)程處理后,就會(huì)生成不同的對(duì)象,所以不能通過(guò)直接比較是否是同一個(gè)對(duì)象來(lái)判斷是不是同一個(gè)客戶端對(duì)象,Android中專門用來(lái)處理跨進(jìn)程調(diào)用回調(diào)的類就是RemoteCallbackList,RemoteCallbackList還能自動(dòng)處理App端異常死亡情況,這種情況會(huì)自動(dòng)移除已經(jīng)注冊(cè)的回調(diào).RemoteCallbackList使用非常簡(jiǎn)單,注冊(cè)和移除分別調(diào)用register()和unregister()即可,遍歷所有Callback稍微麻煩一點(diǎn),代碼參考上面的sendEventToRemote()方法.可以看到,我們測(cè)試用的的系統(tǒng)服務(wù)邏輯很簡(jiǎn)單,注冊(cè)和移除Callback調(diào)用RemoteCallbackList對(duì)應(yīng)方法即可,sendEvent()方法在App端調(diào)用的基礎(chǔ)上,在字符串后面加上"remote"后回調(diào)給App,每個(gè)方法也加了log方便理解流程,服務(wù)端代碼就完成了.五、注冊(cè)系統(tǒng)服務(wù)
代碼寫(xiě)好后,要注冊(cè)到SystemServer中,所有系統(tǒng)服務(wù)都運(yùn)行在名為system_server的進(jìn)程中,我們要把編寫(xiě)好的服務(wù)加進(jìn)去,SystemServer中有很多服務(wù),我們把我們的系統(tǒng)服務(wù)加到最后面,對(duì)應(yīng)路徑和代碼如下:
frameworks/base/services/java/com/android/server/SystemServer.java通過(guò)ServiceManager將服務(wù)加到SystemServer中,名字使用SystemEventManager.SERVICE,后面獲取服務(wù)會(huì)通過(guò)名字來(lái)獲取.此時(shí),如果直接編譯運(yùn)行,開(kāi)機(jī)后會(huì)出現(xiàn)如下錯(cuò)誤:
ESystemServer:java.lang.SecurityException
ESELinux:avc:
denied
{add}forservice=test_systemeventpid=1940uid=1000scontext=u:r:system_server:s0tcontext=u:object_r:default_android_service:s0tclass=service_managerpermissive=0
ESystemServer:java.lang.SecurityExceptionESELinux:avc:
denied
{add}forservice=test_systemeventpid=1940uid=1000scontext=u:r:system_server:s0tcontext=u:object_r:default_android_service:s0tclass=service_managerpermissive=0這個(gè)是沒(méi)有Selinux權(quán)限,我們需要加上添加服務(wù)的權(quán)限,代碼如下:首先定義類型,test_systemevent要和添加服務(wù)用的名字保持一致
system/sepolicy/service_contextssystem/sepolicy/service.te加入上面代碼后,編譯刷機(jī)開(kāi)機(jī)后,服務(wù)就能正常運(yùn)行了.六、注冊(cè)Manager
系統(tǒng)服務(wù)運(yùn)行好了,接下來(lái)就是App怎么獲取的問(wèn)題了,App獲取系統(tǒng)服務(wù),我們也用通用接口:
在調(diào)用getSystemService()之前,需要先注冊(cè),代碼如下:frameworks/base/core/java/android/app/SystemServiceRegistry.java注冊(cè)后,如果你在App里面通過(guò)getSystemService(SystemEventManager.SERVICE);獲取Manager并調(diào)用接口,會(huì)發(fā)現(xiàn)又會(huì)出錯(cuò),又是Selinux權(quán)限問(wèn)題:
ESELinux:avc:
denied
{find}forservice=test_systemeventpid=4123uid=10035scontext=u:r:untrusted_app:s0:c512,c768tcontext=u:object_r:test_systemevent_service:s0tclass=service_managerpermissive=0
ESELinux:avc:
denied
{find}forservice=test_systemeventpid=4123uid=10035scontext=u:r:untrusted_app:s0:c512,c768tcontext=u:object_r:test_systemevent_service:s0tclass=service_managerpermissive=0說(shuō)是沒(méi)有find權(quán)限,因此又要加權(quán)限,修改代碼如下:
system/sepolicy/untrusted_app.te這個(gè)Selinux的知識(shí)有興趣自己去學(xué)一下,報(bào)了什么權(quán)限,就按照錯(cuò)誤信息去對(duì)應(yīng)文件添加權(quán)限.至此,系統(tǒng)代碼修改完成了,編譯系統(tǒng)刷機(jī),下面通過(guò)App調(diào)用.七、App調(diào)用
文件拷貝和準(zhǔn)備:
我們需要復(fù)制三個(gè)文件到App中,兩個(gè)AIDL文件,一個(gè)Manager文件:
IEventCallback.aidl
ISystemEvent.aidl
SystemEventManager.java
IEventCallback.aidl
ISystemEvent.aidl
SystemEventManager.java所有AIDL文件和java文件,在App工程中的包名和路徑都需要和系統(tǒng)保持一致,這三個(gè)文件App不能做任何修改,除非系統(tǒng)源碼中也做對(duì)應(yīng)修改,總的來(lái)說(shuō),這三個(gè)文件App和系統(tǒng)中要完全保持一致,類名包名和包路徑都需一致,復(fù)制這三個(gè)文件到工程中后,編譯后,調(diào)用方式如下.獲取服務(wù):這里AndroidStudio可能會(huì)報(bào)getSystemService()參數(shù)不是Context里面的某個(gè)服務(wù)的錯(cuò)誤,可以直接忽略,不影響編譯.注冊(cè)/取消注冊(cè):調(diào)用:測(cè)試Log如下:
DSystemEventManager:SystemEventManagerinit
DSystemEventService:registerpid:3944uid:10035result:true
DSystemEventService:remotecallbackcount:1
DSystemEvent:type:1value:teststringremote
DSystemEventService:unregisterpid:3944uid:10035result:true
DSystemEventManager:SystemEventManagerinit
DSystemEventService:registerpid:3944uid:10035result:true
DSystemEventService:remotecallbackcount:1
DSystemEvent:type:1value:teststringremote
DSystemEventService:unregisterpid:3944uid:10035result:true可以看到調(diào)用了服務(wù)端并成功收到服務(wù)端拼接的字符串.八、添加JNI部分代碼
我們一般添加系統(tǒng)服務(wù),可能是為了調(diào)用驅(qū)動(dòng)里面的代碼,所有一般要用JNI部分代碼,這里不是講怎么編寫(xiě)JNI代碼,而是說(shuō)下系統(tǒng)服務(wù)中已有的JNI代碼,我們可以直接在這基礎(chǔ)上增加我們的功能.JNI部分代碼位置為:
frameworks/base/services/core/jni/
frameworks/base/services/core/jni/
編譯對(duì)應(yīng)mk為:
frameworks/base/services/Android.mk
frameworks/base/services/core/jni/Android.mk
frameworks/base/services/Android.mk
frameworks/base/services/core/jni/Android.mk
此部分代碼直接編譯為libandroid_servers動(dòng)態(tài)庫(kù),在SystemServer進(jìn)行加載:
frameworks/base/services/java/com/android/server/SystemServer.java如果需要添加JNI部分代碼,直接在
frameworks/base/services/core/jni/目錄下增加對(duì)應(yīng)文件,
在frameworks/base/services/core/jni/Android.
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 淺談對(duì)民間文藝演出團(tuán)體的管理與扶持
- 關(guān)于開(kāi)挖 合同范本
- 公司助理合同范例
- 情感事務(wù)所創(chuàng)業(yè)計(jì)劃書(shū)模板
- 2025年度建筑工程施工合同勞務(wù)分包與材料采購(gòu)合同管理
- 做門頭合同范本
- 企業(yè)聯(lián)銷合同范本
- 農(nóng)村樓房購(gòu)買合同范本
- 2025年度國(guó)際物流人才培訓(xùn)與派遣合同
- 出版作品合同范本
- 四川省自貢市2024-2025學(xué)年上學(xué)期八年級(jí)英語(yǔ)期末試題(含答案無(wú)聽(tīng)力音頻及原文)
- 2025-2030年中國(guó)汽車防滑鏈行業(yè)競(jìng)爭(zhēng)格局展望及投資策略分析報(bào)告新版
- 2025年上海用人單位勞動(dòng)合同(4篇)
- 二年級(jí)上冊(cè)口算題3000道-打印版讓孩子口算無(wú)憂
- 高中英語(yǔ)北師大版必修第一冊(cè)全冊(cè)單詞表(按單元編排)
- 2025年生物安全年度工作計(jì)劃
- 人教版數(shù)學(xué)六年級(jí)下冊(cè)全冊(cè)核心素養(yǎng)目標(biāo)教學(xué)設(shè)計(jì)
- 通用電子嘉賓禮薄
- 山西省煤炭運(yùn)銷集團(tuán)有限公司王家?guī)X煤礦井筒工程施工組織設(shè)計(jì)
- 新概念英語(yǔ)第三冊(cè)課后習(xí)題答案詳解
- 有機(jī)化學(xué)共振論
評(píng)論
0/150
提交評(píng)論