




下載本文檔
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、在編寫Android應用程序時,我們一般將一些計算型的邏輯放在一個獨立的進程來處理,這樣主進程仍然可以流暢地響應界面事件,提高用戶體驗。Android系統(tǒng)為我們提供了一個Service類,我們可以實現(xiàn)一個以Service為基類的服務子類,在里面實現(xiàn)自己的計算型邏輯,然后在主進程通過startService函數來啟動這個服務。在本文中,將詳細分析主進程是如何通過startService函數來在新進程中啟動自定義服務的。在主進程調用startService函數時,會通過Binder進程間通信機制來通知ActivitManagerService來創(chuàng)建新進程,并且啟動指定的服務。在Android系統(tǒng)中
2、,Binder進程間通信機制使用非常廣泛,因此,希望讀者在繼續(xù)閱讀下面的內容之前,對Android系統(tǒng)和Binder進程間通信機制有一定的了解,具體可以參考前面Android進程間通信(IPC)機制Binder簡要介紹和學習計劃一文。關于startService的具體用法,可以參考前面Android系統(tǒng)匿名共享內存Ashmem(AnonymousSharedMemory)簡要介紹和學習計劃一文中用到的實例,它是Activity類的一個成員函數:viewplain1.packageshy.luo.ashmem;.publicclassClientextendsActivityimp
3、lementsOnClickListener6.7.IMemoryServicememoryService=null;8.9.10.Override11.publicvoidonCreate(BundlesavedInstanceState)12.13.14.IMemoryServicems=getMemoryService();15.if(ms=null)16.startService(newIntent("shy.luo.ashmem.server");17.else18.Log.i(LOG_TAG,"MemoryServicehasstarted."
4、;);2.23.Log.i(LOG_TAG,"ClientActivityCreated.");25.26.27.)這里的"shy.luo.ashmem.server是在程序配置文件AndroidManifest.xml配置的Service的名字,用來告訴Android系統(tǒng)它所要啟動的服務的名字:viewplain1. <manifestxmlns:android="2. package="shy.luo.ashmem"3. android:sharedUserId="android.uid.sys
5、tem"4. android:versionCode="1"5.android:versionName="1.0">6. <applicationandroid:icon=p_name">7. ."drawable/icon"android:label=string/ap8. <service9. android:enabled="true"10. android:name=".Server"11. android:process=".Ser
6、ver'12. <intent-filter>13. <actionandroid:name=14. <categoryandroid:name=ULT"/>15. </intent-filter>>"shy.luo.ashmem.server"/>"ent.category.DEFA16. </service>17. </application>18. </manifest>這里,名字“shy.luo.ashmem.server對應的
7、服務類為shy.luo.ashmem.Server,下面語句:viewplain1.startService(newIntent("shy.luo.ashmem.server");就表示要在一個新的進程中啟動shy.luo.ashmem.Server這個服務類,它必須繼承于Android平臺提供的Service類:viewplain1. packageshy.luo.ashmem;2.3.1從圖中可以看出,Activity繼承了Contextwrapper類,而在Contextwrapper類中,實現(xiàn)了startService函數。在Contextwrapper類中,有一個
8、成員變量mBase,卜面,我們來看看Activity類中的startService成員函數是如何實現(xiàn)的先來看看Activity的類圖:.1.publicclassServerextendsServiceDatai圖1RaturtScr的皿acrvicc;Inrtcrrt);CfflnpsnenlNjimc4starrservice;service:君meCort口或叩pqrISllHlrtl-i-1ranssat(cade:irt,dais:FBrcai(:Psrc>el.Ibb:irft:bHlear
9、OverridepublicIBinderonBind(Intentintent)returnnullOverridepublicvoidonCreate()日trrmTActiwitySrUt訓mpl+s:artSeiiceistrvic巴.Intsnt1:C匚mponentharneBindwPr。仃-nOtjiectimgdqirtdaiq.Paiccl.icy%pH口口耨.時:;boM型同ctiwityMiEg心rPrxy4如H。*FlHlJr-l4人麗加川仙口州PfdhYrtma#Eindar卜calfer-lApplcstcnT-1jr|?eix>jc:»'
10、Intern,rwO'VcType:Strng'匚qipcrEFgn正IMivitMariiflg«r產ENFfHHIApplet!CTlTTMd£Blvl££FIr1口I-yITyp-S|rij-11eIrIH11"它是一個Contextlmpl實例,而Contextlmpl類和Contextwrapper類一樣繼承于Context類,Contextwrapper類的startService函數最終過調用Contextlmpl類的startService函數來實現(xiàn)。這種類設計方法在設計模式里面,就稱之為裝飾模式(Decorat
11、or),或者包裝模式(Wrapper)。在Contextlmpl類的startService類,最終又調用了ActivityManagerProxy類的startService來實現(xiàn)啟動服務的操作,看到這里的Proxy關鍵字,回憶一下前面Android系統(tǒng)進程間通信Binder機制在應用程序框架層的Java接口源代碼分析這篇文章,就會知道ActivityManagerProxy是一個Binder對象的遠程接口了,而這個Binder對象就是我們前面所說的ActivityManagerService了。這個ActivityManagerService類實現(xiàn)在frameworks/base/serv
12、ices/java/com/android/server/am/ActivityManagerService.java文件中,它是Binder進程間通信機制中的Server角色,它是隨機啟動的。隨機啟動的Server是在frameworks/base/services/java/com/android/server/SystemServer.java文件里面進行啟動的,我們來看一下ActivityManagerService啟動相關的代碼:viewplain1. classServerThreadextendsThread. Override6. publicvoidrun()7
13、.8. 9.10. /Criticalservices.11. try12.13. .14.15. context=ActivityManagerService.main(factoryTest);16.17. .18.19. ActivityManagerService.setSystemProcess();20.21. .22.23. catch(RuntimeExceptione)7.28.Slog.e()"System","Failurestartingcoreservice'29. 30.31. .32.33. 首先是調用Ac
14、tivityManagerService.main函數來創(chuàng)建一個ActivityManagerService實例,然后通過調用ActivityManagerService.setSystemProcess函數把這個Binder實例添加Binder進程間通信機制的守護進程ServiceManager中去:viewplain.5.publicfinalclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback6.7.
15、3.24.25.staticActivityManagerServicemSelf;publicstaticvoidsetSystemProcess()tryActivityManagerServicem=mSelf;ServiceManager.addService("activity",m);catch(PackageManager.NameNotFoundExceptione)publicstaticfinalContextmain(intfactoryTest)28.29. Ac
16、tivityManagerServicem=thr.mService;30. mSelf=m;31.32. .33.34. 35. 這樣,ActivityManagerService就啟動起來了?;氐紸ctivityManagerProxy類的startService函數中,它定義在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:viewplain1. classActivityManagerProxyimplementsIActivityManager2. 3.4.5. publicComponentNa
17、mestartService(IApplicationThreadcaller,Intentservice,6. StringresolvedType)throwsRemoteException7. 8. Parceldata=Parcel.obtain();9. Parcelreply=Parcel.obtain();10. data.writeInterfaceToken(IActivityManager.descriptor);11. data.writeStrongBinder(caller!=null?caller.asBinder():null);12. service.write
18、ToParcel(data,0);13. data.writeString(resolvedType);14. mRemote.transact(START_SERVICE_TRANSACTION,data,reply,0);15. reply.readException();16. ComponentNameres=ComponentName.readFromParcel(reply);17. data.recycle();18. reply.recycle();19. returnres;20. 21.22.23. 參數service是一個Intent實例,它里面指定了要啟動的服務的名稱,
19、就是前面我們所說的"shy.luo.ashmem.server”了。參數caller是一個lApplicationThread實例,它是一個在主進程創(chuàng)建的一個Binder對象。在Android應用程序中,每一個進程都用一個ActivityThread實例來表示,而在ActivityThread類中,有一個成員變量mAppThread,它是一個ApplicationThread實例,實現(xiàn)了lApplicationThread接口,它的作用是用來輔助ActivityThread類來執(zhí)行一些操作,這個我們在后面會看到它是如何用來啟動服務的。參數resolvedType是一個字符串,它表示s
20、ervice這個Intent的MIME類型,它是在解析Intent時用到的。在這個例子中,我們沒有指定這個Intent的MIME類型,因此,這個參數為nulloActivityManagerProxy類的startService函數把這三個參數寫入到data本地變量去,接著通過mRemote.transact函數進入到Binder驅動程序,然后Binder驅動程序喚醒正在等待Client請求的ActivityManagerService進程,最后進入到ActivityManagerService的startService函數中。ActivityManagerService的startServi
21、ce函數的處理流程如下圖所示:點擊查看大圖在這個序列圖中,一共有20個步驟,下面說明每一步。Step1.ActivityManagerService.startService這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1.publicfinalclassActivityManagerServiceextendsActivityManagerNative2.implementsWatchdog.Monitor,BatteryStatsImpl.
22、BatteryCallback. publicComponentNamestartService(IApplicationThreadcaller,Intentservice,7. StringresolvedType)8. /Refusepossibleleakedfiledescriptors9. if(service!=null&&service.hasFileDescriptors()=true)10. thrownewIllegalArgumentException("FiledescriptorspassedinIntent");1
23、1. 12.13. synchronized(this)14. finalintcallingPid=Binder.getCallingPid();15. finalintcallingUid=Binder.getCallingUid();16. finallongorigId=Binder.clearCallingIdentity();17. ComponentNameres=startServiceLocked(caller,service,18. resolvedType,callingPid,callingUid);19. Binder.restoreCallingIdentity(o
24、rigId);20. returnres;21. 22. 6. 這里的參數caller、service和resolvedType分別對應ActivityManagerProxy.startService傳進來的三個參數。Step2.ActivityManagerService.startServiceLocked這個函數同樣定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. publicfinalclassActivityManag
25、erServiceextendsActivityManagerNative2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3.46. ComponentNamestartServiceLocked(IApplicationThreadcaller,7. Intentservice,StringresolvedType,8. intcallingPid,intcallingUid)9. synchronized(this)10. .11.12. ServiceLookupResultres=13. retrieveSer
26、viceLocked(service,resolvedType,14. callingPid,callingUid);15.16. .17.18. ServiceRecordr=res.record;19.20. .21.22. if(!bringUpServiceLocked(r,service.getFlags(),false)23. returnnewComponentName("!","Serviceprocessisbad");24. 25. ;26. 27. 1. 函數首先通過retrieveSer
27、viceLocked來解析service這個Intent,就是解析前面我們在AndroidManifest.xml定義的Service標簽的intent-filter相關內容,然后將解析結果放在res.record中,然后繼續(xù)調用bringUpServiceLocked進一步處理。Step3.ActivityManagerService.bringUpServiceLocked這個函數同樣定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. public
28、finalclassActivityManagerServiceextendsActivityManagerNative2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3.46. privatefinalbooleanbringUpServiceLocked(ServiceRecordr,7. intintentFlags,booleanwhileRestarting)8.9. .10.11. finalStringappName=cessName;12.13. .14.15. /Notrunning-get
29、itstarted,andenqueuethisservicerecord16. /tobeexecutedwhentheappcomesup.17. if(startProcessLocked(appName,r.appInfo,true,intentFlags,18. "service",,false)=null)19.20. .21.22. returnfalse;23. 24.25. if(!mPendingServices.contains(r)26. mPendingServices.add(r);27. 28.29. returntrue;30.3
30、1. 5. 這里的appName便是我們前面在AndroidManifest.xml文件定義service標簽時指定的android:process屬性值了,即“.Server。"接著調用startProcessLocked函數來創(chuàng)建一個新的進程,以便加載自定義的Service類。最后將這個ServiceRecord保存在成員變量mPendingServices列表中,后面會用到。Step4.ActivityManagerService.startProcessLocked這個函數同樣定義在frameworks/base/services/java/com/and
31、roid/server/am/ActivityManagerService.java文件中:viewplain1.publicfinalclassActivityManagerServiceextendsActivityManagerNative2.implementsWatchdog.Monitor,BatteryStatsImpl.Ba3.4.5.tteryCallback6.7.privatefinalvoidstartProcessLocked(ProcessRecordapp,StringhostingType,StringhostingNameStr)1.try12
32、.13.14.15.intpid=Process.start("android.app.ActivityThread"16.mSimpleProcessManagement?cessName:nul0.l,uid,uid,gids,debugFlags,null);21.if(pid=0|pid=MY_PID)5.elseif(pid>0)26.27.app.pid=pid;app.removed=false;28.synchronized(mPidsSelfLocked)29.this.mPidsSelfLock
33、ed.put(pid,app);30.31.32.else6.37.catch(RuntimeExceptione)1.43. )7. )這里調用Process.start函數創(chuàng)建了一個新的進程,指定新的進程執(zhí)行android.app.ActivityThread類。最后將表示這個新進程的ProcessRecord保存在mPidSelfLocked列表中,后面會用到。Step5.Process.start這個函數定義在frameworks/base/core/java/android/os/Process.java文件中,這個函數我們
34、就不看了,有興趣的讀者可以自己研究一下。在這個場景中,它就是新建一個進程,然后導入android.app.ActivityThread這個類,然后執(zhí)行它的main函數。Step6.ActivityThread.main這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:viewplain1. publicfinalclassActivityThread. publicstaticfinalvoidmain(String口args)6.7. .8.9. Looper.prepareMainLoope
35、r();10.11. .12.13. ActivityThreadthread=newActivityThread();14. thread.attach(false);15.16. .17.18. Looper.100P();19.20. .21.23.24. .25. )26. 注意,執(zhí)行到這里的時候,已經是在上一步創(chuàng)建的新進程里面了,即這里的進程是用來啟動服務的,原來的主進程已經完成了它的命令,返回了。前面我們提到,在Android應用程序中,每一個進程對應一個ActivityThread實例,所以,這個函數會創(chuàng)建一個thread實例,然后調用ActivityThread.attach函
36、數進一步處理。Step7.ActivityThread.attach這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:viewplain1.publicfinalclassActivityThread. privatefinalvoidattach(booleansystem)6.7. .8.9. if(!system)10.11. .12.13. IActivityManagermgr=ActivityManagerNative.getDefault();14. try15. mgr.atta
37、chApplication(mAppThread);16. catch(RemoteExceptionex)17. 18. else19.20. .21.22. 23.24. .25.26. 28.29.30. 從Step6中,這里傳進來的參數system為false。成員變量mAppThread是一個ApplicationThread實例,我們在前面已經描述過這個實例的作用,它是用來輔助ActivityThread來執(zhí)行一些操作的。調用ActivityManagerNative.getDefault函數得到ActivityManagerService的遠程接口,即ActivityManage
38、rProxy,接著調用它的attachApplication函數。Step8.ActivityManagerProxy.attachApplication這個函數定義在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:viewplain1. classActivityManagerProxyimplementsIActivityManager2. 3.4.5. publicvoidattachApplication(IApplicationThreadapp)throwsRemoteException6. 7
39、. Parceldata=Parcel.obtain();8. Parcelreply=Parcel.obtain();9. data.writeInterfaceToken(IActivityManager.descriptor);10. data.writeStrongBinder(app.asBinder();11. mRemote.transact(ATTACH_APPLICATION_TRANSACTION,data,reply,0);12. reply.readException();13. data.recycle();14. reply.recycle();15. 16.17.
40、18.19. 這個函數主要是將新進程里面的IApplicationThread實例通過Binder驅動程序傳遞給ActivityManagerService。Step9.ActivityManagerService.attachApplication這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. publicfinalclassActivityManagerServiceextendsActivityManagerNative2. impl
41、ementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3.45.6.publicfinalvoidattachApplication(IApplicationThreadthread)7.8. synchronized(this)9. intcallingPid=Binder.getCallingPid();10. finallongorigId=Binder.clearCallingIdentity();11. attachApplicationLocked(thread,callingPid);12. Binder.restoreCa
42、llingIdentity(origId);13. 14. 15. 1617. 18.這里通過調用attachApplicationLocked函數進一步處理。Step10.ActivityManagerService.attachApplicationLocked這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. publicfinalclassActivityManagerServiceextendsActivityManagerNativ
43、e2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback3.45.6.privatefinalbooleanattachApplicationLocked(IApplicationThreadthread,8. /Findtheapplicationrecordthatisbeingattached.eithervia9. /thepidifwearerunninginmultipleprocesses,orjustpullthe10. /nextapprecordifweareemulatingprocesswithano
44、nymousthreads.11. ProcessRecordapp;12. if(pid!=MY_PID&&pid>=0)13. synchronized(mPidsSelfLocked)14. app=mPidsSelfLocked.get(pid);15. 16. elseif(mStartingProcesses.size()>0)17. app=mStartingProcesses.remove(0);18. app.setPid(pid);19. else20. app=null;21. 22.23. .24.25.26. StringprocessNa
45、me=cessName;27.28. .29.30. app.thread=thread;31.32. .33.34. booleanbadApp=false;35.36. .37.38. /Findanyservicesthatshouldberunninginthisprocess.39. if(!badApp&&mPendingServices.size()>0)40. ServiceRecordsr=null;41. try42. for(inti=0;i<mPendingServices.size();i+)43. sr=mPendingSe
46、rvices.get(i);44. if(.uid!=sr.appInfo.uid45. |!processName.equals(cessName)46. continue;47. 48.49. mPendingServices.remove(i);50. i-;51. realStartServiceLocked(sr,app);52. didSomething=true;53. 54. catch(Exceptione)55.56. .57.58. 59. 60.61. .62.63. returntrue;64. 8. 回憶一下在上面的S
47、tep4中,以新進程的pid值作為key值保存了一個ProcessRecord在mPidsSelfLocked列表中,這里先把它取出來,存放在本地變量app中,并且將cessName保存在本地變量processName中。再回憶一下在上面的Step3中,在成員變量mPendingServices中,保存了一個ServiceRecord,這里通過進程uid和進程名稱將它找出來,然后通過realStartServiceLocked函數來進一步處理。Step11.ActivityManagerService.realStartServiceLocked這個函數定義在frameworks
48、/base/services/java/com/android/server/am/ActivityManagerService.java文件中:viewplain1. classActivityManagerProxyimplementsIActivityManager2. 3.4.5. privatefinalvoidrealStartServiceLocked(ServiceRecordr,6. ProcessRecordapp)throwsRemoteException7.8. .10. r.app=app;11.12. .13.14. try15.16. .17.18. app.th
49、read.scheduleCreateService(r,r.serviceInfo);19.20. .21.22. finally23.24. .25.26. 27.28. .29.30. 4. 這里的app.thread是一個ApplicationThread對象的遠程接口,它是在上面的Step6創(chuàng)建ActivityThread對象時作為ActivityThread對象的成員變量同時創(chuàng)建的,然后在Step9中傳過來的。然后調用這個遠程接口的scheduleCreateService函數回到原來的ActivityThread對象中執(zhí)行啟動服務的操作。Step12.Appl
50、icationThreadProxy.scheduleCreateService這個函數定義在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:viewplain1. classApplicationThreadProxyimplementsIApplicationThread2.5. publicfinalvoidscheduleCreateService(IBindertoken,Serviceinfoinfo)6. throwsRemoteException7. Parceldata=Parcel.
51、obtain();8. data.writeinterfaceToken(IApplicationThread.descriptor);9. data.writeStrongBinder(token);10. info.writeToParcel(data,0);11. mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION,data,null12. IBinder.FLAG_ONEWAY);13. data.recycle();14. 8. 這里通過Binder驅動程序回到新進程的ApplicationThread對象中去
52、執(zhí)行scheduleCreateService函數。Step13.ApplicationThread.scheduleCreateService這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:viewplain1. publicfinalclassActivityThread. privatefinalclassApplicationThreadextendsApplicationThreadNative6.7. .8.9. publicfinalvoidscheduleCreateServi
53、ce(IBindertoken,10. ServiceInfoinfo)11. CreateServiceDatas=newCreateServiceData();12. s.token=token;13. =info;14.15. queueOrSendMessage(H.CREATE_SERVICE,s);16. 17. .18.19. 3. 這里調用ActivityThread的queueOrSendMessage將一個CreateServiceData數據放到消息隊列中去,并且分開這個消息。注意,這里已經是在上面Step4創(chuàng)建的新進程中執(zhí)行了。Step14.ActivityThread.queueOrSendMessage這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:viewplain1. publicfinalclassActivityThread. privatefinalvoidqueueOrSendMessage(intwhat,Objec
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 材料疲勞斷裂影響因素研究重點基礎知識點
- 食用油火災應急處置預案(3篇)
- 火災應急預案范文文庫(3篇)
- 動態(tài)編程與遞歸解法試題及答案
- 網絡管理員職業(yè)素養(yǎng)提升及試題答案
- 企業(yè)品牌建設與戰(zhàn)略目標試題及答案
- 編程語言趨勢及其對職業(yè)發(fā)展的影響試題及答案
- 2025年VB考試重要資料與試題及答案
- 網絡管理員職業(yè)要求與考試試題答案
- 2025年軟考增分技巧探討試題及答案
- 樂山大佛完整版本
- 校長在班主任培訓會上的講話范文
- 北京市海淀區(qū)2023-2024學年五年級上學期數學期末試卷
- GB/T 19609-2024卷煙用常規(guī)分析用吸煙機測定總粒相物和焦油
- 建筑工程一切險保險單
- 浙江寧波市杭州灣大橋發(fā)展有限公司招聘筆試題庫2024
- 2024年內蒙古呼和浩特市中考英語試卷真題(含答案解析)
- 多視圖靜態(tài)異常檢測
- 醫(yī)療垃圾分類及轉運院感考核試題與答案
- 核反應堆熱工分析課程設計
- AQ 1011-2005 煤礦在用主通風機系統(tǒng)安全檢測檢驗規(guī)范(正式版)
評論
0/150
提交評論