編輯:關於Android編程
目錄:
1.TheBasics
最基本的
2.Declaringaserviceinthemanifest
在服務清單中配置
3.CreatingaStartedServiceExtendingtheIntentServiceclass
創建一個服務擴展類
4.ExtendingtheServiceclass
繼承Serrvice類
5.Startingaservice
開始服務
6.Stoppingaservice
結束服務
7.CreatingaBoundService
綁定服務
8.SendingNotificationstotheUser
向用戶發送通知
9.RunningaServiceintheForeground
在前台運行服務
10.ManagingtheLifecycleofaService
管理服務的生命周期
11.Implementingthelifecyclecallbacks
實現生命周期回調
AServiceisanapplicationcomponentthatcanperformlong-runningoperationsinthebackgroundanddoesnotprovideauserinterface.Anotherapplicationcomponentcanstartaserviceanditwillcontinuetoruninthebackgroundeveniftheuserswitchestoanotherapplication.Additionally,acomponentcanbindtoaservicetointeractwithitandevenperforminterprocesscommunication(IPC).Forexample,aservicemighthandlenetworktransactions,playmusic,performfileI/O,orinteractwithacontentprovider,allfromthebackground.
服務是一個應用程序組件,可以在後台執行長時間運行的操作,不提供用戶界面。另一個應用程序組件可以啟動一個服務,它將繼續在後台運行,即使用戶切換到另一個應用程序。此外,一個組件可以綁定到一個服務與它交互,甚至執行進程間通信(IPC)。例如,一個服務可能處理網絡交易,播放音樂,執行文件I/O,或與一個內容提供者交互,所有的背景。
Aservicecanessentiallytaketwoforms:
一個服務基本上可以采取兩種形式:
Started
Aserviceis"started"whenanapplicationcomponent(suchasanactivity)startsitbycallingstartService().Oncestarted,aservicecanruninthebackgroundindefinitely,evenifthecomponentthatstarteditisdestroyed.Usually,astartedserviceperformsasingleoperationanddoesnotreturnaresulttothecaller.Forexample,itmightdownloadoruploadafileoverthenetwork.Whentheoperationisdone,theserviceshouldstopitself.
開始
服務是“開始”,當一個應用程序組件(例如,一個活動)啟動它通過調用由startService()。一旦開始,一個服務可以無限期地在後台運行,即使開始它的組件被摧毀。通常,開始服務執行一個操作,不向調用者返回一個結果。例如,它可能通過網絡下載或上傳文件。當操作完成,服務應該停止本身。
Bound
Aserviceis"bound"whenanapplicationcomponentbindstoitbycallingbindService().Aboundserviceoffersaclient-serverinterfacethatallowscomponentstointeractwiththeservice,sendrequests,getresults,andevendosoacrossprocesseswithinterprocesscommunication(IPC).Aboundservicerunsonlyaslongasanotherapplicationcomponentisboundtoit.Multiplecomponentscanbindtotheserviceatonce,butwhenallofthemunbind,theserviceisdestroyed.
綁定
服務是“綁定”當一個應用程序組件綁定到它通過調用bindService()。綁定服務提供了一個客戶機-服務器接口,允許組件與服務交互,發送請求,得到結果,甚至跨進程與進程間通信(IPC)。綁定服務只要運行另一個應用程序組件綁定到它。多個組件可以綁定到服務,但是當他們解開,服務被摧毀。
Althoughthisdocumentationgenerallydiscussesthesetwotypesofservicesseparately,yourservicecanworkbothways—itcanbestarted(torunindefinitely)andalsoallowbinding.It'ssimplyamatterofwhetheryouimplementacouplecallbackmethods:onStartCommand()toallowcomponentstostartitandonBind()toallowbinding.
盡管這些文檔一般分別討論了這兩種類型的服務,您的服務可以工作兩個方面,它可以開始無限期(運行),也允許綁定。這是簡單的你是否實現兩個回調方法:onStartCommand()允許組件開始,onBind()允許綁定。
Regardlessofwhetheryourapplicationisstarted,bound,orboth,anyapplicationcomponentcanusetheservice(evenfromaseparateapplication),inthesamewaythatanycomponentcanuseanactivity—bystartingitwithanIntent.However,youcandeclaretheserviceasprivate,inthemanifestfile,andblockaccessfromotherapplications.ThisisdiscussedmoreinthesectionaboutDeclaring?the?service?in?the?manifest.
無論您的應用程序啟動時,綁定,或者兩者兼有,任何應用程序組件可以使用服務(甚至從一個單獨的應用程序),以同樣的方式,任何組件都可以使用一個活動開始與一個意圖。然而,您可以聲明與私人服務,在清單文件,阻止訪問其他應用程序。這一節討論更多的是關於聲明的服務清單。
Caution:Aservicerunsinthemainthreadofitshostingprocess—theservicedoesnotcreateitsownthreadanddoesnotruninaseparateprocess(unlessyouspecifyotherwise).Thismeansthat,ifyourserviceisgoingtodoanyCPUintensiveworkorblockingoperations(suchasMP3playbackornetworking),youshouldcreateanewthreadwithintheservicetodothatwork.Byusingaseparatethread,youwillreducetheriskofApplicationNotResponding(ANR)errorsandtheapplication'smainthreadcanremaindedicatedtouserinteractionwithyouractivities.
警告:一個服務運行在主線程的托管進程(服務不創建自己的線程和不運行在一個單獨的進程(除非您指定)。這意味著,如果您的服務將做任何CPU密集型工作或阻塞操作(如MP3播放或網絡),您應該創建一個新線程內的服務工作。通過使用一個單獨的線程,您將減少風險的應用程序沒有響應”(ANR)錯誤和應用程序的主線程可以仍然致力於用戶交互活動。
onStartCommand()
Thesystemcallsthismethodwhenanothercomponent,suchasanactivity,requeststhattheservicebestarted,bycallingstartService().Oncethismethodexecutes,theserviceisstartedandcanruninthebackgroundindefinitely.Ifyouimplementthis,itisyourresponsibilitytostoptheservicewhenitsworkisdone,bycallingstopSelf()orstopService().(Ifyouonlywanttoprovidebinding,youdon'tneedtoimplementthismethod.)
onStartCommand()
系統調用這個方法當另一個組件,比如一個活動,要求服務啟動,通過調用由startService()。此方法執行後,服務啟動,可以在後台運行下去。如果你實現這個,是你的責任停止服務工作完成後,通過調用stopSelf()或stopService()。(如果你只是想提供綁定,您不需要實現此方法)。
onBind()
Thesystemcallsthismethodwhenanothercomponentwantstobindwiththeservice(suchastoperformRPC),bycallingbindService().Inyourimplementationofthismethod,youmustprovideaninterfacethatclientsusetocommunicatewiththeservice,byreturninganIBinder.Youmustalwaysimplementthismethod,butifyoudon'twanttoallowbinding,thenyoushouldreturnnull.
onBind()
系統調用該方法當另一個組件想綁定的服務(如執行RPC),通過調用bindService()。在你實現這種方法,您必須提供一個接口,客戶使用與服務進行通信,通過返回一個內部。你必須實現這個方法,但是如果你不希望允許綁定,那麼您應該返回null。
onCreate()
Thesystemcallsthismethodwhentheserviceisfirstcreated,toperformone-timesetupprocedures(beforeitcallseitheronStartCommand()oronBind()).Iftheserviceisalreadyrunning,thismethodisnotcalled.
onCreate()
系統調用此方法在創建服務第一,執行一次性安裝程序(之前調用要麼onStartCommand()oronBind())。如果服務已經運行,調用這個方法並不是。
onDestroy()
Thesystemcallsthismethodwhentheserviceisnolongerusedandisbeingdestroyed.Yourserviceshouldimplementthistocleanupanyresourcessuchasthreads,registeredlisteners,receivers,etc.Thisisthelastcalltheservicereceives.
onDestroy()
系統調用此方法不再使用服務時,被摧毀了。您的服務應該實現這個清理任何資源,如線程注冊偵聽器,接收器,等等。這是最後一個調用服務。
IfacomponentstartstheservicebycallingstartService()(whichresultsinacalltoonStartCommand()),thentheserviceremainsrunninguntilitstopsitselfwithstopSelf()oranothercomponentstopsitbycallingstopService().
如果一個組件啟動服務通過調用由startService()(它導致調用onStartCommand()),然後服務仍然運行,直到它停止本身stopSelf()或停止它通過調用另一個組件stopService()。
IfacomponentcallsbindService()tocreatetheservice(andonStartCommand()isnotcalled),thentheservicerunsonlyaslongasthecomponentisboundtoit.Oncetheserviceisunboundfromallclients,thesystemdestroysit.
如果一個組件callsbindService()來創建服務(onStartCommand()不是),然後服務只要運行組件綁定到它。一旦釋放從所有客戶服務,系統破壞它。
TheAndroidsystemwillforce-stopaserviceonlywhenmemoryislowanditmustrecoversystemresourcesfortheactivitythathasuserfocus.Iftheserviceisboundtoanactivitythathasuserfocus,thenit'slesslikelytobekilled,andiftheserviceisdeclaredtorunintheforeground(discussedlater),thenitwillalmostneverbekilled.Otherwise,iftheservicewasstartedandislong-running,thenthesystemwillloweritspositioninthelistofbackgroundtasksovertimeandtheservicewillbecomehighlysusceptibletokilling—ifyourserviceisstarted,thenyoumustdesignittogracefullyhandlerestartsbythesystem.Ifthesystemkillsyourservice,itrestartsitassoonasresourcesbecomeavailableagain(thoughthisalsodependsonthevalueyoureturnfromonStartCommand(),asdiscussedlater).Formoreinformationaboutwhenthesystemmightdestroyaservice,seetheProcessesandThreadingdocument.
Android系統將force-stop服務只有當內存低,必須恢復系統資源的活動用戶的焦點。如果服務被綁定到一個活動用戶的焦點,那就不太可能被殺,如果聲明的服務是運行在前台(稍後討論),那麼它將幾乎從未被殺死。否則,如果服務是啟動和長期,則系統會降低它在後台任務列表位置隨著時間的推移和服務將成為高度容易killing-if啟動你的服務,那麼你必須設計優雅地處理系統重新啟動。如果系統殺死你的服務,再次重新啟動它一旦資源可用(盡管這也取決於你從onStartCommand返回的值(),稍後討論)。更多信息時,系統可能會摧毀一個服務,流程和Threadingdocument。
Inthefollowingsections,you'llseehowyoucancreateeachtypeofserviceandhowtouseitfromotherapplicationcomponents.
在下面幾節中,您將看到如何創建每個類型的服務和如何使用它從其他應用程序組件。
Aserviceissimplyacomponentthatcanruninthebackgroundevenwhentheuserisnotinteractingwithyourapplication.Thus,youshouldcreateaserviceonlyifthatiswhatyouneed.
你應該使用一個服務或一個線程?
服務是一個簡單的組件,可以在後台運行,即使用戶與應用程序交互。因此,您應該只創建一個服務如果這是你所需要的東西。
Aserviceissimplyacomponentthatcanruninthebackgroundevenwhentheuserisnotinteractingwithyourapplication.Thus,youshouldcreateaserviceonlyifthatiswhatyouneed.
Ifyouneedtoperformworkoutsideyourmainthread,butonlywhiletheuserisinteractingwithyourapplication,thenyoushouldprobablyinsteadcreateanewthreadandnotaservice.Forexample,ifyouwanttoplaysomemusic,butonlywhileyouractivityisrunning,youmightcreateathreadinonCreate(),startrunningitinonStart(),thenstopitinonStop().AlsoconsiderusingAsyncTaskorHandlerThread,insteadofthetraditionalThreadclass.SeetheProcesses?and?Threadingdocumentformoreinformationaboutthreads.
Rememberthatifyoudouseaservice,itstillrunsinyourapplication'smainthreadbydefault,soyoushouldstillcreateanewthreadwithintheserviceifitperformsintensiveorblockingoperations.
服務是一個簡單的組件,可以在後台運行,即使用戶與應用程序交互。因此,您應該只創建一個服務如果這是你所需要的東西。
如果您需要執行工作外你的主線程,但只有在用戶與應用程序交互,那麼你應該而不是創建一個新的線程,而不是服務。例如,如果你想播放一些音樂,但只有當你的活動正在運行,您可以創建一個線程在onCreate(),在onStart()開始運行它,然後停止在onStop()。也可以考慮使用AsyncTask或HandlerThread,而不是傳統的線程類。有關更多信息,請參見進程和線程文檔關於線程。
記住,如果你使用一個服務,它仍然運行在應用程序的主線程在默認情況下,所以你應該還是創建一個新的線程內的服務如果它執行密集或阻塞操作。
Declaringaserviceinthemanifest//在manifest中配置
Likeactivities(andothercomponents),youmustdeclareallservicesinyourapplication'smanifestfile.
像activity(和其他組件),你必須在您的應用程序的清單文件聲明所有服務。
Todeclareyourservice,adda
聲明服務:在標簽下添加一個
復制代碼:
...
...
Thereareotherattributesyoucanincludeinthe
還有其他屬性可以包含在
Seethe
在服務清單中查看關於
Justlikeanactivity,aservicecandefineintentfiltersthatallowothercomponentstoinvoketheserviceusingimplicitintents.Bydeclaringintentfilters,componentsfromanyapplicationinstalledontheuser'sdevicecanpotentiallystartyourserviceifyourservicedeclaresanintentfilterthatmatchestheintentanotherapplicationpassestostartService().
就像一個活動,一個服務可以定義一個intent過濾器,允許其他組件調用該服務隱式意圖。通過聲明意圖過濾器,從任何應用程序組件安裝在用戶的設備可以開始你的服務如果你聲明了一個意圖過濾器意圖相匹配的另一個應用程序通過由startService()。
Ifyouplanonusingyourserviceonlylocally(otherapplicationsdonotuseit),thenyoudon'tneedto(andshouldnot)supplyanyintentfilters.Withoutanyintentfilters,youmuststarttheserviceusinganintentthatexplicitlynamestheserviceclass.Moreinformationaboutstartingaserviceisdiscussedbelow.
如果你打算只在本地使用你的服務(其他應用程序不使用),那麼你不需要(也不應該)提供任何意圖過濾器。沒有意圖過濾器,您必須使用一個顯示的意圖來啟動該服務,明確服務類名。下面將討論關於啟動服務的更多信息。
Additionally,youcanensurethatyourserviceisprivatetoyourapplicationonlyifyouincludetheandroid:exportedattributeandsetitto"false".Thisiseffectiveevenifyourservicesuppliesintentfilters.
另外,如果你設置android:exported屬性是“false”的話你必須保證你的服務是受保護的應用程序。即使你的服務有意圖過濾器,這也是有效的。
Formoreinformationaboutcreatingintentfiltersforyourservice,seetheIntentsandIntentFiltersdocument.
要了解更多關於服務創建過濾器的信息,參考意圖和意圖過濾器文件。
AstartedserviceisonethatanothercomponentstartsbycallingstartService(),resultinginacalltotheservice'sonStartCommand()method.
一個開始了的服務是由另一個組件通過調用startService()方法開啟的,然後直接調用service的onStartCommand()方法。
當啟動一個服務,組件會啟動一個獨立的聲明周期並且service會一直在後台運行,即使啟動它的組件被銷毀。因此服務是通過調用stopSelf()來停止的,或者是另一個組件通過調用stopService()來停止它。
AnapplicationcomponentsuchasanactivitycanstarttheservicebycallingstartService()andpassinganIntentthatspecifiestheserviceandincludesanydatafortheservicetouse.TheservicereceivesthisIntentintheonStartCommand()method.
應用程序組件,如一個activity可以通過調用startService()方法來啟動並且通過意圖指定服務所需的所有數據,指定服務的服務,包括任何數據使用。服務在onStartCommand()方法接收到這個意圖。
Forinstance,supposeanactivityneedstosavesomedatatoanonlinedatabase.TheactivitycanstartacompanionserviceanddeliveritthedatatosavebypassinganintenttostartService().TheservicereceivestheintentinonStartCommand(),connectstotheInternetandperformsthedatabasetransaction.Whenthetransactionisdone,theservicestopsitselfanditisdestroyed.
例如,一個activity需要保存數據在一個在線數據庫。activity可以開啟一個同伴服務並把它保存的數據釋放給一個由startService()的意圖。服務在onStartCommand()方法中接受意圖,連接到互聯網和執行數據庫操作。當事務完成,服務停止並被摧毀。
Caution:Aservicesrunsinthesameprocessastheapplicationinwhichitisdeclaredandinthemainthreadofthatapplication,bydefault.So,ifyourserviceperformsintensiveorblockingoperationswhiletheuserinteractswithanactivityfromthesameapplication,theservicewillslowdownactivityperformance.Toavoidimpactingapplicationperformance,youshouldstartanewthreadinsidetheservice.
警告:默認情況下,一個服務運行在聲明它的主線程中運行。因此,如果用戶在相同的應用程序中執行密集或阻塞操作時,服務將減緩活動性能。為了避免影響應用程序的性能,您應該開啟一個新的線程。
Traditionally,therearetwoclassesyoucanextendtocreateastartedservice:
傳統上,有兩個類可以被繼承來創建一個啟動服務:
Service
Thisisthebaseclassforallservices.Whenyouextendthisclass,it'simportantthatyoucreateanewthreadinwhichtodoalltheservice'swork,becausetheserviceusesyourapplication'smainthread,bydefault,whichcouldslowtheperformanceofanyactivityyourapplicationisrunning.
這是所有服務的基類。繼承這個類時,重要的是,你需要創建一個新的線程來做服務的工作,因為該服務在應用程序的主線程下,默認情況下,這可能會減緩應用程序運行時的性能。
IntentService
ThisisasubclassofServicethatusesaworkerthreadtohandleallstartrequests,oneatatime.Thisisthebestoptionifyoudon'trequirethatyourservicehandlemultiplerequestssimultaneously.AllyouneedtodoisimplementonHandleIntent(),whichreceivestheintentforeachstartrequestsoyoucandothebackgroundwork.
這是一個服務的子類,使用一個工作線程來處理所有開始請求,一次一個。在你不需要你的服務同時處理多個請求的情況下這是最好的選擇。你需要做的就是實現onHandleIntent()方法,它為每個請求進行響應,這樣你就可以開始做後台工作。
Thefollowingsectionsdescribehowyoucanimplementyourserviceusingeitheronefortheseclasses.
下面是描述如何使用這些類實現你的服務。
ExtendingtheIntentServiceclass//繼承IntentService類
Becausemoststartedservicesdon'tneedtohandlemultiplerequestssimultaneously(whichcanactuallybeadangerousmulti-threadingscenario),it'sprobablybestifyouimplementyourserviceusingtheIntentServiceclass.
因為最開始服務不需要同時處理多個請求(可以是一個不安全的多線程),如果你實現你的服務最好使用IntentService類。
TheIntentServicedoesthefollowing:
IntentService類做一下幾點:
1.CreatesadefaultworkerthreadthatexecutesallintentsdeliveredtoonStartCommand()separatefromyourapplication'smainthread.
創建一個默認的線程,在onStartCommand()將所有的意圖傳遞給獨立於應用程序的主線程。
2.CreatesaworkqueuethatpassesoneintentatatimetoyouronHandleIntent()implementation,soyouneverhavetoworryaboutmulti-threading.
創建一個隊列,將意圖傳遞給你的onHandleIntent(),所以你永遠不必擔心多線程。
3.Stopstheserviceafterallstartrequestshavebeenhandled,soyouneverhavetocallstopSelf().
在請求被處理之後停止服務,所以你不必調用stopSelf()方法。
4.ProvidesdefaultimplementationofonBind()thatreturnsnull.
提供的默認實現方法onBind()返回null。
5.ProvidesadefaultimplementationofonStartCommand()thatsendstheintenttotheworkqueueandthentoyouronHandleIntent()implementation.
提供了一個默認實現方法onStartCommand(),將發送意圖到工作隊列,然後發送到onHandleIntent()。
AllthisaddsuptothefactthatallyouneedtodoisimplementonHandleIntent()todotheworkprovidedbytheclient.(Though,youalsoneedtoprovideasmallconstructorfortheservice.)
綜上所述,所有您需要在onHandleIntent()需要做的工作都由客戶提供。(雖然,您還需要提供服務的小型構造函數)。
Here'sanexampleimplementationofIntentService:
下面是一個IntentService示例:
復制代碼:
publicclassHelloIntentServiceextendsIntentService{
/**
*Aconstructorisrequired,andmustcallthesuperIntentService(String)
*constructorwithanamefortheworkerthread.
*/
publicHelloIntentService(){
super("HelloIntentService");
}
/**
*TheIntentServicecallsthismethodfromthedefaultworkerthreadwith
*theintentthatstartedtheservice.Whenthismethodreturns,IntentService
*stopstheservice,asappropriate.
*/
@Override
protectedvoidonHandleIntent(Intentintent){
//Normallywewoulddosomeworkhere,likedownloadafile.
//Foroursample,wejustsleepfor5seconds.
longendTime=System.currentTimeMillis()+5*1000;
while(System.currentTimeMillis()
synchronized(this){
try{
wait(endTime-System.currentTimeMillis());
}catch(Exceptione){
}
}
}
}
}
That'sallyouneed:aconstructorandanimplementationofonHandleIntent().
這是你所需要的:一個構造函數和實現onHandleIntent()。
Ifyoudecidetoalsooverrideothercallbackmethods,suchasonCreate(),onStartCommand(),oronDestroy(),besuretocallthesuperimplementation,sothattheIntentServicecanproperlyhandlethelifeoftheworkerthread.
如果你決定也重寫其它回調方法,如onCreate(),onStartCommand(),或onDestroy(),一定要調用超級實現類,以便IntentService能妥善處理線程的生命。
Forexample,onStartCommand()mustreturnthedefaultimplementation(whichishowtheintentgetsdeliveredtoonHandleIntent()):
例如,onStartCommand()必須返回默認實現類(意圖如何交付給onHandleIntent()):
復制代碼:
@OverridepublicintonStartCommand(Intentintent,intflags,intstartId){Toast.makeText(this,"servicestarting",Toast.LENGTH_SHORT).show();returnsuper.onStartCommand(intent,flags,startId);}
BesidesonHandleIntent(),theonlymethodfromwhichyoudon'tneedtocallthesuperclassisonBind()(butyouonlyneedtoimplementthatifyourserviceallowsbinding).
除了onHandleIntent(),唯一的方法,你不需要調用超類是onBind()(但你只需要實現,如果您的服務允許綁定)。
Inthenextsection,you'llseehowthesamekindofserviceisimplementedwhenextendingthebaseServiceclass,whichisalotmorecode,butwhichmightbeappropriateifyouneedtohandlesimultaneousstartrequests.
在下一節中,您將看到同樣的服務是如何實現的擴展基礎服務類的時候,這是一個更多的代碼,但這可能是合適的,如果你需要處理並發請求開始。
啟動一個服務
YoucanstartaservicefromanactivityorotherapplicationcomponentbypassinganIntent(specifyingtheservicetostart)tostartService().TheAndroidsystemcallstheservice'sonStartCommand()methodandpassesittheIntent.(YoushouldnevercallonStartCommand()directly.)
您可以從一個活動或其他應用程序組件啟動一個服務通過一個目的(指定服務開始)Intent的startService()方法,。Android系統調用服務的onStartCommand()方法並傳遞它的意圖。(你不應該叫onStartCommand()直接)。
Forexample,anactivitycanstarttheexampleserviceintheprevioussection(HelloSevice)usinganexplicitintentwithstartService():
例如,一個活動可以開始一個顯式意圖使用startService(),例如前一節中的示例服務(HelloSevice):
Intentintent=newIntent(this,HelloService.class);startService(intent);
ThestartService()methodreturnsimmediatelyandtheAndroidsystemcallstheservice'sonStartCommand()method.Iftheserviceisnotalreadyrunning,thesystemfirstcallsonCreate(),thencallsonStartCommand().
立即返回,startService()方法,Android系統調用服務的sonStartCommand()方法。如果服務沒有運行,系統首先調用onCreate(),然後調用callsonStartCommand()方法。
Iftheservicedoesnotalsoprovidebinding,theintentdeliveredwithstartService()istheonlymodeofcommunicationbetweentheapplicationcomponentandtheservice.However,ifyouwanttheservicetosendaresultback,thentheclientthatstartstheservicecancreateaPendingIntentforabroadcast(withgetBroadcast())anddeliverittotheserviceintheIntentthatstartstheservice.Theservicecanthenusethebroadcasttodeliveraresult.
如果服務不提供綁定,交付的意圖與startService()是應用程序組件之間唯一的通信模式和服務。然而,如果你希望服務發回一個結果,然後啟動服務的客戶端,則可以創建PendingIntent廣播(withgetBroadcast())和交付的服務啟動的目的服務。服務可以使用廣播發表的結果
Multiplerequeststostarttheserviceresultinmultiplecorrespondingcallstotheservice'sonStartCommand().However,onlyonerequesttostoptheservice(withstopSelf()orstopService())isrequiredtostopit.
多個請求啟動相應服務去調用服務的onStartCommand()會產生多樣的結果。然而,當只有一個請求停止服務時(例如通過stopSelf()或stopService())必須去阻止它。
停止服務
Astartedservicemustmanageitsownlifecycle.Thatis,thesystemdoesnotstopordestroytheserviceunlessitmustrecoversystemmemoryandtheservicecontinuestorunafteronStartCommand()returns.So,theservicemuststopitselfbycallingstopSelf()oranothercomponentcanstopitbycallingstopService().
開始服務必須管理自己的生命周期。也就是說,系統並不能阻止或破壞服務,除非它必須恢復系統內存和服務onStartCommand後繼續運行()返回,服務本身必須停止去調用stopSelf()或另一個組件通過調用stopService()去阻止它。
OncerequestedtostopwithstopSelf()orstopService(),thesystemdestroystheserviceassoonaspossible.
一旦通過stopSelf()或stopService()去停止請求,系統就會很快的破壞服務。
However,ifyourservicehandlesmultiplerequeststoonStartCommand()concurrently,thenyoushouldn'tstoptheservicewhenyou'redoneprocessingastartrequest,becauseyoumighthavesincereceivedanewstartrequest(stoppingattheendofthefirstrequestwouldterminatethesecondone).Toavoidthisproblem,youcanusestopSelf(int)toensurethatyourrequesttostoptheserviceisalwaysbasedonthemostrecentstartrequest.Thatis,whenyoucallstopSelf(int),youpasstheIDofthestartrequest(thestartIddeliveredtoonStartCommand())towhichyourstoprequestcorresponds.TheniftheservicereceivedanewstartrequestbeforeyouwereabletocallstopSelf(int),thentheIDwillnotmatchandtheservicewillnotstop.
然而,如果你的服務同時處理了多個請求去onStartCommand(),那麼當你處理一個請求開始,你不應該停止服務,因為你可能已經收到了新的開始請求(停在第一個請求終止第二個)。為了避免這個問題,您可以使用stopSelf(int),以確保你的請求停止服務,它總是基於最近的請求開始。也就是說,當你使用stopSelf(int)時,您就會終止ID請求的開始(startId交付toonStartCommand())。
如果服務收到了新的開始請求之前你調用stopSelf(int),ID將不會匹配,服務也將不會停止
Caution:It'simportantthatyourapplicationstopsitsserviceswhenit'sdoneworking,toavoidwastingsystemresourcesandconsumingbatterypower.Ifnecessary,othercomponentscanstoptheservicebycallingstopService().Evenifyouenablebindingfortheservice,youmustalwaysstoptheserviceyourselfifiteverreceivedacalltoonStartCommand().
注意:當您的應用程序停止工作時您的應用就會停止活動,這樣做是為了避免系統資源浪費和消耗電池,它是非常重要的。如果有必要,還可以阻止其他組件的服務callingstopService()。
即使你啟用了綁定的服務,,如果它調用onStartCommand()方法,那麼你必須停止服務。
Formoreinformationaboutthelifecycleofaservice,seethesectionbelowaboutManaging?the?Lifecycle?of?a?Service.
關於生命周期服務的更多信息,參見下面一節關於管理服務的生命周期
創建一個綁定服務
AboundserviceisonethatallowsapplicationcomponentstobindtoitbycallingbindService()inordertocreatealong-standingconnection(andgenerallydoesnotallowcomponentstostartitbycallingstartService()).
綁定服務,允許應用程序組件綁定到它,通過調用bindService()來創建一個長期的連接(一般不允許組件開始通過callingstartService())。
Youshouldcreateaboundservicewhenyouwanttointeractwiththeservicefromactivitiesandothercomponentsinyourapplicationortoexposesomeofyourapplication'sfunctionalitytootherapplications,throughinterprocesscommunication(IPC).
您應該創建一個綁定服務,當你想與服務交互活動和其他組件在應用程序或向其他應用程序公開您的應用程序的一些功能時,通過進程間通信(IPC)。
Tocreateaboundservice,youmustimplementtheonBind()callbackmethodtoreturnanIBinderthatdefinestheinterfaceforcommunicationwiththeservice.OtherapplicationcomponentscanthencallbindService()toretrievetheinterfaceandbegincallingmethodsontheservice.Theservicelivesonlytoservetheapplicationcomponentthatisboundtoit,sowhentherearenocomponentsboundtotheservice,thesystemdestroysit(youdonotneedtostopaboundserviceinthewayyoumustwhentheserviceisstartedthroughonStartCommand()).
創建一個綁定服務,您必須實現onBind()回調方法,返回一個ibinder定義的接口用來溝通服務。其他應用程序組件可以調用bindService()來檢索界面,開始調用服務方法。服務僅僅是寄居在應用程序上來達到綁它的效果,所以當沒有組件綁定到服務時,系統會破壞它(你不需要停止綁定服務的時候必須在啟動服務時throughonStartCommand())。
Tocreateaboundservice,thefirstthingyoumustdoisdefinetheinterfacethatspecifieshowaclientcancommunicatewiththeservice.ThisinterfacebetweentheserviceandaclientmustbeanimplementationofIBinderandiswhatyourservicemustreturnfromtheonBind()callbackmethod.OncetheclientreceivestheIBinder,itcanbegininteractingwiththeservicethroughthatinterface.
創建一個綁定服務,你必須做的第一件事是定義接口,指定客戶端如何與服務通信。這個接口在服務和客戶機之間必須實現ofIBinder()方法,客戶端服務必須返回onBind()回調方法,一旦客戶端收到theIBinder,它就可以開始通過該接口與服務交互。
Multipleclientscanbindtotheserviceatonce.Whenaclientisdoneinteractingwiththeservice,itcallsunbindService()tounbind.Oncetherearenoclientsboundtotheservice,thesystemdestroystheservice.
多個客戶端可以綁定到服務。當客戶端與服務交互,它callsunbindService()來解開。一旦沒有客戶端綁定到服務,服務系統破壞。
Therearemultiplewaystoimplementaboundserviceandtheimplementationismorecomplicatedthanastartedservice,sotheboundservicediscussionappearsinaseparatedocumentaboutBound?Services.
有多種方法來實現綁定服務,實現綁定服務比開始服務更復雜,因此,在一個單獨的文檔綁定服務討論綁定服務。
向用戶發送通知
Oncerunning,aservicecannotifytheuserofeventsusingToast?NotificationsorStatus?Bar?Notifications.
一旦運行,服務可以通知該活動的用戶使用toast來的到通知或狀態欄得到通知。
Atoastnotificationisamessagethatappearsonthesurfaceofthecurrentwindowforamomentthendisappears,whileastatusbarnotificationprovidesaniconinthestatusbarwithamessage,whichtheusercanselectinordertotakeanaction(suchasstartanactivity).
當toast出的消息出現在當前窗口的表面時,過一會兒就消失了,而提供了一個狀態欄通知圖標在狀態欄信息,用戶可以選擇采取一個動作(如啟動一個活動)。
Usually,astatusbarnotificationisthebesttechniquewhensomebackgroundworkhascompleted(suchasafilecompleteddownloading)andtheusercannowactonit.Whentheuserselectsthenotificationfromtheexpandedview,thenotificationcanstartanactivity(suchastoviewthedownloadedfile).
通常,在一些背景工作完成(如文件下載完成)或者用戶現在進行操作時,一個狀態欄的通知是最好的方法。當用戶通過擴展視圖來選擇通知時,這個通知可以啟動一個活動(如查看下載的文件)。
SeetheToast?NotificationsorStatus?Bar?Notificationsdeveloperguidesformoreinformation.
領會toast或狀態欄通知獲得消息指導開發人員獲得更多的信息
RunningaServiceintheForeground
Aforegroundserviceisaservicethat'sconsideredtobesomethingtheuserisactivelyawareofandthusnotacandidateforthesystemtokillwhenlowonmemory.Aforegroundservicemustprovideanotificationforthestatusbar,whichisplacedunderthe"Ongoing"heading,whichmeansthatthenotificationcannotbedismissedunlesstheserviceiseitherstoppedorremovedfromtheforeground.
前台服務是一種服務,被認為是用戶正在意識到,因此不適合系統殺時內存不足。前台服務必須提供狀態欄通知,這是把“正在進行”的標題下,這意味著通知不能被解雇,除非服務被停止或從前台移除。
Forexample,amusicplayerthatplaysmusicfromaserviceshouldbesettorunintheforeground,becausetheuserisexplicitlyawareofitsoperation.Thenotificationinthestatusbarmightindicatethecurrentsongandallowtheusertolaunchanactivitytointeractwiththemusicplayer.
例如,一個音樂播放器,播放音樂,從服務應設置在前台運行,因為用戶很關心它的操作。狀態欄中的通知可能指示當前的歌曲,並允許用戶啟動一個活動與音樂播放器交互
Torequestthatyourservicerunintheforeground,callstartForeground().Thismethodtakestwoparameters:anintegerthatuniquelyidentifiesthenotificationandtheNotificationforthestatusbar.Forexample:
要求在前台運行您的服務,電話startforeground()。這種方法需要兩個參數:一個唯一標識的通知和狀態欄通知整數。例如:
Notificationnotification=newNotification(R.drawable.icon,getText(R.string.ticker_text),
System.currentTimeMillis());
IntentnotificationIntent=newIntent(this,ExampleActivity.class);
PendingIntentpendingIntent=PendingIntent.getActivity(this,0,notificationIntent,0);
notification.setLatestEventInfo(this,getText(R.string.notification_title),
getText(R.string.notification_message),pendingIntent);
startForeground(ONGOING_NOTIFICATION,notification);
Toremovetheservicefromtheforeground,callstopForeground().Thismethodtakesaboolean,indicatingwhethertoremovethestatusbarnotificationaswell.Thismethoddoesnotstoptheservice.However,ifyoustoptheservicewhileit'sstillrunningintheforeground,thenthenotificationisalsoremoved.
從前台移除服務,電話stopforeground()。該方法以一個布爾值,指示是否刪除狀態欄通知等。此方法不會停止服務。然而,如果你停止服務,而它仍然運行在前台,然後通知也被取消了。
Note:ThemethodsstartForeground()andstopForeground()wereintroducedinAndroid2.0(APILevel5).Inordertorunyourserviceintheforegroundonolderversionsoftheplatform,youmustusetheprevioussetForeground()method—seethestartForeground()documentationforinformationabouthowtoprovidebackwardcompatibility.
注意:方法startForeground()和stopForeground()介紹了Android2.0(API級別5)。為了運行在前台服務的舊版本的平台,您必須使用前面setForeground()method-seestartForeground()的文檔信息如何提供向後兼容性。
Formoreinformationaboutnotifications,seeCreating?Status?Bar?Notifications.
關於通知的更多信息,請參閱創建狀態欄通知。
管理服務的生命周期
Thelifecycleofaserviceismuchsimplerthanthatofanactivity.However,it'sevenmoreimportantthatyoupaycloseattentiontohowyourserviceiscreatedanddestroyed,becauseaservicecanruninthebackgroundwithouttheuserbeingaware.
服務的生命周期比活動的簡單的多。然而,更重要的是,你要密切關注你的服務的創建和銷毀,因為服務可以在後台運行,用戶不知道。
Theservicelifecycle—fromwhenit'screatedtowhenit'sdestroyed—canfollowtwodifferentpaths:
1.Astartedservice
2.啟動服務
TheserviceiscreatedwhenanothercomponentcallsstartService().TheservicethenrunsindefinitelyandmuststopitselfbycallingstopSelf().AnothercomponentcanalsostoptheservicebycallingstopService().Whentheserviceisstopped,thesystemdestroysit..
服務時創建另一個組件調用startservice()。然後服務無限期地運行,必須停止本身通過調用stopself()。另一個組件也可以通過callingstopservice()停止服務。當服務停止,系統銷毀它。
1.Aboundservice
2.綁定服務
Theserviceiscreatedwhenanothercomponent(aclient)callsbindService().TheclientthencommunicateswiththeservicethroughanIBinderinterface.TheclientcanclosetheconnectionbycallingunbindService().Multipleclientscanbindtothesameserviceandwhenallofthemunbind,thesystemdestroystheservice.(Theservicedoesnotneedtostopitself.)
服務時創建另一個組件(客戶端)稱bindservice()。客戶服務通過一個IBinder接口進行通信。客戶可以通過callingunbindservice()關閉連接。多個客戶端可以綁定到相同的服務時,他們都斷開,系統銷毀服務。(服務不不需要自行停止。)
Thesetwopathsarenotentirelyseparate.Thatis,youcanbindtoaservicethatwasalreadystartedwithstartService().Forexample,abackgroundmusicservicecouldbestartedbycallingstartService()withanIntentthatidentifiesthemusictoplay.Later,possiblywhentheuserwantstoexercisesomecontrolovertheplayerorgetinformationaboutthecurrentsong,anactivitycanbindtotheservicebycallingbindService().Incaseslikethis,stopService()orstopSelf()doesnotactuallystoptheserviceuntilallclientsunbind.
這兩種方法並不是完全分開的。那就是,你可以綁定到一個服務已經開始withstartservice()。例如,一個背景音樂服務可以由一個意圖確認音樂播放呼叫startservice()開始。後來,可能是當用戶想練習控制播放器或取得當前歌曲的信息,一個活動可以綁定到服務通過調用bindservice()。在這樣的情況下,stopservice()或stopself()實際上並沒有停止服務,直到所有的客戶數據。
實施的生命周期回調
Likeanactivity,aservicehaslifecyclecallbackmethodsthatyoucanimplementtomonitorchangesintheservice'sstateandperformworkattheappropriatetimes.Thefollowingskeletonservicedemonstrateseachofthelifecyclemethods:
活動一樣,服務生命周期回調方法,你可以實現監控服務狀態的改變,並在適當的時候進行工作。下面的每個骨架服務演示了生命周期方法:
publicclassExampleServiceextendsService{
intmStartMode;//indicateshowtobehaveiftheserviceiskilled
IBindermBinder;//interfaceforclientsthatbind
booleanmAllowRebind;//indicateswhetheronRebindshouldbeused
@Override
publicvoidonCreate(){
//Theserviceisbeingcreated
}
@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
//Theserviceisstarting,duetoacalltostartService()
returnmStartMode;
}
@Override
publicIBinderonBind(Intentintent){
//AclientisbindingtotheservicewithbindService()
returnmBinder;
}
@Override
publicbooleanonUnbind(Intentintent){
//AllclientshaveunboundwithunbindService()
returnmAllowRebind;
}
@Override
publicvoidonRebind(Intentintent){
//AclientisbindingtotheservicewithbindService(),
//afteronUnbind()hasalreadybeencalled
}
@Override
publicvoidonDestroy(){
//Theserviceisnolongerusedandisbeingdestroyed
}}
Note:Unliketheactivitylifecyclecallbackmethods,youarenotrequiredtocallthesuperclassimplementationofthesecallbackmethods.
注:與活動的生命周期回調方法,你不需要調用的回調方法的父類的實現。
Figure2.Theservicelifecycle.ThediagramontheleftshowsthelifecyclewhentheserviceiscreatedwithstartService()andthediagramontherightshowsthelifecyclewhentheserviceiscreatedwithbindService().
圖2。服務生命周期。左邊的圖顯示了生命周期服務時創建的withstartservice()和右邊的圖顯示了生命周期當服務與bindservice()創建。
Byimplementingthesemethods,youcanmonitortwonestedloopsoftheservice'slifecycle:
通過實現這些方法,你可以監控兩個嵌套的循環服務的生命周期:
1.TheentirelifetimeofaservicehappensbetweenthetimeonCreate()iscalledandthetimeonDestroy()returns.Likeanactivity,aservicedoesitsinitialsetupinonCreate()andreleasesallremainingresourcesinonDestroy().Forexample,amusicplaybackservicecouldcreatethethreadwherethemusicwillbeplayedinonCreate(),thenstopthethreadinonDestroy().
TheonCreate()andonDestroy()methodsarecalledforallservices,whetherthey'recreatedbystartService()orbindService().
1.TheactivelifetimeofaservicebeginswithacalltoeitheronStartCommand()oronBind().EachmethodishandedtheIntentthatwaspassedtoeitherstartService()orbindService(),respectively.
Iftheserviceisstarted,theactivelifetimeendsthesametimethattheentirelifetimeends(theserviceisstillactiveevenafteronStartCommand()returns).Iftheserviceisbound,theactivelifetimeendswhenonUnbind()returns.
如果該服務已啟動,有效壽命結束,整個壽命結束同一時間(甚至在onstartcommand()返回服務仍然是激活的)。如果服務綁定,有效壽命結束whenonunbind()返回。
Note:AlthoughastartedserviceisstoppedbyacalltoeitherstopSelf()orstopService(),thereisnotarespectivecallbackfortheservice(there'snoonStop()callback).So,unlesstheserviceisboundtoaclient,thesystemdestroysitwhentheserviceisstopped—onDestroy()istheonlycallbackreceived.
注:雖然一開始的服務是由一個叫到stopself()或stopservice()停了下來,沒有服務的相應的回調(沒有onstop()回調)。所以,除非服務綁定到客戶端,系統銷毀它當服務是stopped-ondestroy()是唯一回調接收。
Figure2illustratesthetypicalcallbackmethodsforaservice.AlthoughthefigureseparatesservicesthatarecreatedbystartService()fromthosecreatedbybindService(),keepinmindthatanyservice,nomatterhowit'sstarted,canpotentiallyallowclientstobindtoit.So,aservicethatwasinitiallystartedwithonStartCommand()(byaclientcallingstartService())canstillreceiveacalltoonBind()(whenaclientcallsbindService()).
圖2說明了一個服務的典型回調方法。雖然這是由startservice()的bindservice()創造的人物將服務,請記住,任何服務,不管它是如何開始的,可能允許客戶端綁定到它。因此,一種服務,是最初開始withonstartcommand()(通過客戶端調用startservice())仍然可以接收到呼叫onbind()(當客戶callsbindservice())。
Formoreinformationaboutcreatingaservicethatprovidesbinding,seetheBound?Servicesdocument,whichincludesmoreinformationabouttheonRebind()callbackmethodinthesectionaboutManaging?the?Lifecycle?of?a?Bound?Service.
關於創建提供捆綁服務的更多信息,見綁定服務文檔,其中包括關於onrebind()回調方法在部分關於管理被綁定服務的生命周期的更多信息。
PREVIOUSNEXT
Exceptasnoted,thiscontentislicensedunderApache?2.0.Fordetailsandrestrictions,seetheContent?License.
除非另有說明,這個內容是在Apache2許可。細節和限制,看到內容許可證。
Android4.2r1-13Nov20120:25
About?Android|Legal|Support
AsyncTask原理簡介AsyncTask通過Handler實現異步消息處理。 AsyncTask是一個抽象類,使用的時候必須要實現抽象方法doInBackground
本篇記錄的是Android開發中OkHttp框架的使用,下面介紹OkHttp庫的用法,本篇會給出OkHttp的使用demo,demo中包含了常用的get請求、post請求
承香墨影Android--ColorMatrix改變圖片顏色 前言 本篇博客講解如何通過改變圖片像素點RGB的值的方式,在Android中改變圖片
本人自己在做一個launcher,所以需要處理icon,加陰影和邊框等。這只是一種處理方法,其他的處理方法類似。 效果圖: &