以下內(nèi)容整理自互聯(lián)網(wǎng),僅用于個人學(xué)習(xí)
1. 什么是服務(wù)
服務(wù)是Android中實(shí)現(xiàn)程序后臺運(yùn)行的解決方案,是一個應(yīng)用程序組件,它能夠在后臺執(zhí)行一些耗時較長的操作,它非常適用于去執(zhí)行那些不需要和用戶交互而且要求長期運(yùn)行的任務(wù)。服務(wù)不依賴與任何用戶界面,即時當(dāng)程序被切換到后臺,或者用戶打開另一個應(yīng)用程序,服務(wù)仍然能夠保持正常運(yùn)行。
2. 服務(wù)與線程的區(qū)別
如果你需要在主線程之外執(zhí)行一些工作,但僅當(dāng)用戶與你的應(yīng)用程序交互時才會用到,那你應(yīng)該創(chuàng)建一個新的線程而不是創(chuàng)建服務(wù)。 比如,如果你需要播放一些音樂,但只是當(dāng)你的activity在運(yùn)行時才需要播放,你可以在onCreate()中創(chuàng)建一個線程,在onStart()中開始運(yùn)行,然后在onStop()中終止運(yùn)行。還可以考慮使用AsyncTask或HandlerThread來取代傳統(tǒng)的Thread類。
3. 服務(wù)的分類
按運(yùn)行狀態(tài)分類可分為兩類:前臺服務(wù)和后臺服務(wù)
前臺服務(wù)是指那些經(jīng)常會被用戶關(guān)注的服務(wù),因此內(nèi)存過低時它不會成為被殺的對象。 前臺服務(wù)必須提供一個狀態(tài)欄通知,并會置于“正在進(jìn)行的”(“Ongoing”)組之下。這意味著只有在服務(wù)被終止或從前臺移除之后,此通知才能被解除。
要把服務(wù)設(shè)置為前臺運(yùn)行,可以調(diào)用startForeground()方法。
要從前臺移除服務(wù),可以調(diào)用stopForeground()方法。
按使用分類可分為兩類:本地服務(wù)和遠(yuǎn)程服務(wù)
本地服務(wù)用于應(yīng)用程序內(nèi)部,實(shí)現(xiàn)一些耗時任務(wù),并不占用應(yīng)用程序所屬線程,而是單開線程后臺執(zhí)行。
遠(yuǎn)程服務(wù)用于Android系統(tǒng)內(nèi)部的應(yīng)用程序之間,可被其他應(yīng)用程序復(fù)用,比如天氣預(yù)報服務(wù),其他應(yīng)用程序不需要再寫這樣的服務(wù),調(diào)用已有的即可。可以定義接口并把接口暴露出來,以便其他應(yīng)用進(jìn)行操作。
4. Service生命周期

onStartCommand()的返回值必須是以下常量之一:
START_NOT_STICKY:如果系統(tǒng)在onStartCommand()返回后殺死了服務(wù),則不會重建服務(wù)了,除非還存在未發(fā)送的intent。 當(dāng)服務(wù)不再是必需的,并且應(yīng)用程序能夠簡單地重啟那些未完成的工作時,這是避免服務(wù)運(yùn)行的最安全的選項(xiàng).
START_STICKY:如果系統(tǒng)在onStartCommand()返回后殺死了服務(wù),則將重建服務(wù)并調(diào)用onStartCommand(),但不會再次送入上一個intent, 而是用null intent來調(diào)用onStartCommand() 。除非還有啟動服務(wù)的intent未發(fā)送完,那么這些剩下的intent會繼續(xù)發(fā)送。 這適用于媒體播放器(或類似服務(wù)),它們不執(zhí)行命令,但需要一直運(yùn)行并隨時待命。
START_REDELIVER_INTENT:如果系統(tǒng)在onStartCommand()返回后殺死了服務(wù),則將重建服務(wù)并用上一個已送過的intent調(diào)用onStartCommand()。任何未發(fā)送完的intent也都會依次送入。這適用于那些需要立即恢復(fù)工作的活躍服務(wù),比如下載文件。
5. startService
這類服務(wù)由其它組件調(diào)用startService()來創(chuàng)建,然后保持運(yùn)行,且必須通過調(diào)用stopSelf()自行終止。其它組件也可通過調(diào)用stopService() 終止這類服務(wù)。服務(wù)終止后,系統(tǒng)會把它銷毀。
如果一個Service被startService 方法多次啟動,那么onCreate方法只會調(diào)用一次,onStart將會被調(diào)用多次(對應(yīng)調(diào)用startService的次數(shù)),并且系統(tǒng)只會創(chuàng)建Service的一個實(shí)例(因此你應(yīng)該知道只需要一次stopService調(diào)用)。該Service將會一直在后臺運(yùn)行,而不管對應(yīng)程序的Activity是否在運(yùn)行,直到被調(diào)用stopService,或自身的stopSelf方法。當(dāng)然如果系統(tǒng)資源不足,android系統(tǒng)也可能結(jié)束服務(wù)。
Intent intent = new Intent(this, MyService.class);
startService(intent);
6. bindService
服務(wù)由其它組件(客戶端)調(diào)用bindService()來創(chuàng)建。然后客戶端通過一個IBinder接口與服務(wù)進(jìn)行通信。客戶端可以通過調(diào)用unbindService()來關(guān)閉聯(lián)接。多個客戶端可以綁定到同一個服務(wù)上,當(dāng)所有的客戶端都解除綁定后,系統(tǒng)會銷毀服務(wù)。(服務(wù)不需要自行終止。)
如果一個Service被某個Activity 調(diào)用 Context.bindService 方法綁定啟動,不管調(diào)用 bindService 調(diào)用幾次,onCreate方法都只會調(diào)用一次,同時onStart方法始終不會被調(diào)用。當(dāng)連接建立之后,Service將會一直運(yùn)行,除非調(diào)用Context.unbindService 斷開連接或者之前調(diào)用bindService 的 Context 不存在了(如Activity被finish的時候),系統(tǒng)將會自動停止Service,對應(yīng)onDestroy將被調(diào)用。
Intent intent=new Intent(this,BindService.class);
bindService(intent, ServiceConnection conn, int flags)
服務(wù)綁定的Flag:
Context.BIND_AUTO_CREATE:表示收到綁定請求的時候,如果服務(wù)尚未創(chuàng)建,則即刻創(chuàng)建,在系統(tǒng)內(nèi)存不足需要先摧毀優(yōu)先級組件來釋放內(nèi)存,且只有駐留該服務(wù)的進(jìn)程成為被摧毀對象時,服務(wù)才被摧毀
Context.BIND_DEBUG_UNBIND:通常用于調(diào)試場景中判斷綁定的服務(wù)是否正確,但容易引起內(nèi)存泄漏,因此非調(diào)試目的的時候不建議使用
Context.BIND_NOT_FOREGROUND:表示系統(tǒng)將阻止駐留該服務(wù)的進(jìn)程具有前臺優(yōu)先級,僅在后臺運(yùn)行。
6. 在AndroidManifest文件中聲明服務(wù)
以上的服務(wù)都需要在AndroidManifest文件中聲明
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" ></service>
...
</application>
</manifest>
- android:name:服務(wù)類名(唯一必須的屬性)
- android:label:服務(wù)的名字,如果此項(xiàng)不設(shè)置,那么默認(rèn)顯示的服務(wù)名則為類名
- android:icon:服務(wù)的圖標(biāo)
- android:permission:申明此服務(wù)的權(quán)限,這意味著只有提供了該權(quán)限的應(yīng)用才能控制或連接此服務(wù)
- android:process:表示該服務(wù)是否運(yùn)行在另外一個進(jìn)程,如果設(shè)置了此項(xiàng),那么將會在包名后面加上這段字符串表示另一進(jìn)程的名字
- android:enabled:如果此項(xiàng)設(shè)置為 true,那么 Service 將會默認(rèn)被系統(tǒng)啟動,不設(shè)置默認(rèn)此項(xiàng)為 false
- android:exported:表示該服務(wù)是否能夠被其他應(yīng)用程序所控制或連接,不設(shè)置默認(rèn)此項(xiàng)為 false