天天看點

【Android】Android Service 服務

一、 service簡介

service是android 系統中的四大元件之一(activity、service、broadcastreceiver、contentprovider),它跟activity的級别差不多,但不能自己運作隻能背景運作,并且可以和其他元件進行互動。service可以在很多場合的應用中使用,比如播放多媒體的時候使用者啟動了其他activity這個時候程式要在背景繼續播放,比如檢測sd卡上檔案的變化,再或者在背景記錄你地理資訊位置的改變等等,總之服務總是藏在背景的。

service的啟動有兩種方式:context.startservice() 和 context.bindservice()

二、 service啟動流程

context.startservice() 啟動流程:

context.startservice()  -> oncreate()  -> onstart()  -> service running  -> context.stopservice()  -> ondestroy()  -> service stop 

如果service還沒有運作,則android先調用oncreate(),然後調用onstart();

如果service已經運作,則隻調用onstart(),是以一個service的onstart方法可能會重複調用多次。 

如果stopservice的時候會直接ondestroy,如果是調用者自己直接退出而沒有調用stopservice的話,service會一直在背景運作,該service的調用者再啟動起來後可以通過stopservice關閉service。

是以調用startservice的生命周期為: oncreate  -->  onstart  (可多次調用) -->  ondestroy

context.bindservice()啟動流程:

context.bindservice()  -> oncreate()  -> onbind()  -> service running  -> onunbind()  -> ondestroy()  -> service stop

onbind()将傳回給用戶端一個ibind接口執行個體,ibind允許用戶端回調服務的方法,比如得到service的執行個體、運作狀态或其他操作。這個時候把調用者(context,例如activity)會和service綁定在一起,context退出了,srevice就會調用onunbind->ondestroy相應退出。 

是以調用bindservice的生命周期為:oncreate --> onbind(隻一次,不可多次綁定) --> onunbind --> ondestory。

在service每一次的開啟關閉過程中,隻有onstart可被多次調用(通過多次startservice調用),其他oncreate,onbind,onunbind,ondestory在一個生命周期中隻能被調用一次。

【Android】Android Service 服務
【Android】Android Service 服務

三、 service生命周期 

service的生命周期并不像activity那麼複雜,它隻繼承了oncreate()、onstart()、ondestroy()三個方法

當我們第一次啟動service時,先後調用了oncreate()、onstart()這兩個方法;當停止service時,則執行ondestroy()方法。

這裡需要注意的是,如果service已經啟動了,當我們再次啟動service時,不會在執行oncreate()方法,而是直接執行onstart()方法。

它可以通過service.stopself()方法或者service.stopselfresult()方法來停止自己,隻要調用一次stopservice()方法便可以停止服務,無論調用了多少次的啟動服務方法。

四、 service示例

下面我做了一個簡單的音樂播放的應用,分别使用startservice和bindservice來啟動本地的服務。

activity

service

androidmanifest.xml

注冊activity

注冊service

五、 代碼解析

1、activity中,playmusicservice中通過重寫onclicklistener 接口onclick()方法實作對播放音樂的控制,把音樂各種操作用數字通過intent傳遞給service

然後通過構造一個intent , intent = new intent("com.homer.service.musicservice"); 

其中,com.homer.service.musicservice是 androidmanifest.xml 對service的定義,即上面“注冊service”

2、activity中,音樂播放的控制,利用bundle綁定數字op後,通過 startservice(intent); 服務後發送出去

bundle bundle = new bundle();

bundle.putint("op", op);

intent.putextras(bundle);

startservice(intent);

3、 service中,會處理activity啟動的 startservice(intent);服務,依次調用service的啟動過程:oncreate --> onstart(可多次調用) --> ondestroy

oncreate(),  建立mediaplayer

onstart(),      通過擷取bundle bundle = intent.getextras();,提取int op = bundle.getint("op");,然後執行響應的音樂播放操作

ondestroy(),停止并釋放mediaplayer音樂資源,如果當執行context.stopservice()時調用此方法

4、activity中,onclick()函數中close與exit是執行含義是不同的:

close : 隻是執行了this.finish(); 關閉了本activity窗體,service并沒有被關掉,音樂依然會繼續在背景播放

exit : 先調用了stopservice(intent); 關閉了service服務,在service中會調用3中的ondestroy()停止并釋放音樂資源,後才執行this.finish(); 關閉了本activity窗體

六、 拓展知識(程序和聲明周期)

android作業系統嘗試盡可能長時間的保持應用的程序,但當可用記憶體很低時最終要移走一部分程序。怎樣确定那些程式可以運作,那些要被銷毀,android讓每一個程序在一個重要級的基礎上運作,重要級低的程序最有可能被淘汰,一共有5級,下面這個清單就是按照重要性排列的:

1 一個前台程序顯示的是使用者此時需要處理和顯示的。下列的條件有任何一個成立,這個程序都被認為是在前台運作的。

        a 與使用者正發生互動的。

        b 它控制一個與使用者互動的必須的基本的服務。

        c 有一個正在調用生命周期的回調函數的service(如oncreate()、onstar()、ondestroy())

        d 它有一個正在運作onreceive()方法的廣播接收對象。

隻有少數的前台程序可以在任何給定的時間内運作,銷毀他們是系統萬不得已的、最後的選擇——當記憶體不夠系統繼續運作下去時。通常,在這一點上,裝置已經達到了記憶體分頁狀态,是以殺掉一些前台程序來保證能夠響應使用者的需求。

2 一個可用程序沒有任何前台元件,但它仍然可以影響到使用者的界面。下面兩種情況發生時,可以稱該程序為可用程序。

        它是一個非前台的activity,但對使用者仍然可用(onpause()方法已經被調用)這是可能發生的,例如:前台的activity是一個允許上一個activity可見的對話框,即目前activity半透明,能看到前一個activity的界面,它是一個服務于可用activity的服務。

3 一個服務程序是一個通過調用startservice()方法啟動的服務,并且不屬于前兩種情況。盡管服務程序沒有直接被使用者看到,但他們确實是使用者所關心的,比如背景播放音樂或網絡下載下傳資料。是以系統保證他們的運作,直到不能保證所有的前台可見程式都正常運作時才會終止他們。

4 一個背景程序就是一個非目前正在運作的activity(activity的onstop()方法已經被調用),他們不會對使用者體驗造成直接的影響,當沒有足夠記憶體來運作前台可見程式時,他們将會被終止。通常,背景程序會有很多個在運作,是以他們維護一個lru最近使用程式清單來保證經常運作的activity能最後一個被終止。如果一個activity正确的實作了生命周期的方法,并且儲存它目前狀态,殺死這些程序将不會影響到使用者體驗。

5 一個空線程沒有運作任何可用應用程式組,保留他們的唯一原因是為了設立一個緩存機制,來加快元件啟動的時間。系統經常殺死這些記憶體來平衡系統的整個系統的資源,程序緩存和基本核心緩存之間的資源。

android把程序裡優先級最高的activity或服務,作為這個程序的優先級。例如,一個程序擁有一個服務和一個可見的activity,那麼這個程序将會被定義為可見程序,而不是服務程序。

此外,如果别的程序依賴某一個程序的話,那麼被依賴的程序會提高優先級。一個程序服務于另一個程序,那麼提供服務的程序不會低于獲得服務的程序。例如,如果程序a的一個内容提供商服務于程序b的一個用戶端,或者程序a的一個service被程序b的一個元件綁定,那麼程序a至少擁有和程序b一樣的優先級,或者更高。

因為一個運作服務的程序的優先級高于運作背景activity的程序,一個activity會準備一個長時間運作的操作來啟動一個服務,而不是啟動一個線程–尤其是這個操作可能會拖垮這個activity。例如背景播放音樂的同時,通過照相機向伺服器發送一張照片,啟動一個服務會保證這個操作至少運作在service 程序的優先級下,無論這個activity發生了什麼,廣播接收者應該作為一個空服務而不是簡單的把耗時的操作單獨放在一個線程裡。