標籤:
Android系統也提供了一種稱為“Service”的組件通常在後台運行。Activity 可以用來啟動一個Service,Service啟動後可以保持在後台一直運行,即使啟動它的Activity退出或是切換到別的應用Service也能保持運行狀態。
Service 可以以兩種形式存在:
- Started 當一個如Activity使用startService()來啟動一個Service,一旦Service啟動後,就不受啟動它的Activity控制, 可以在後台長期運行,通常這種Service在後台執行某個費時操作(如下載檔案)不會向啟動它的Activity返回結果。
- Bound 為Activity或是其它程式組件使用bindService()來啟動Service。Bound Service提供了一種Client/Service方法允許調用Service的Activity與Service進行互動:發送請求,取得結果,並 支援處理序間通訊。 一般Bound Service的生命週期和啟動它的Activity相同,多個Activity可以同時綁定一個Service。 當所有Activity 都斷開與Service之間的綁定時。Service自動結束。
雖然Service可以有上述兩種表現形式,這隻是為了說明上的方便,實際上同一個Service可以同時以兩種方式存在,只要實現兩種方法所定義的介面函數就可以了。
建立一個Service,首先需要定義一個Service的子類,然後根據需要重載Service定義的一些核心方法:
- onStartCommand() 當一個Activity調用startService時,Android系統會調用Service的onStartCommand()方法, 前面說過使用startService啟動的Service會在後台長期運行,不受啟動它的Activity控制,因此應用程式有責任來停止 Service,Service也可以調用stopSelf來停止自身。
- onBind() 當一個Activity 使用bindService()來綁定Service時Android系統會調用Service的onBind方法,onBind需要返回一個IBind 對象給調用者(Client)。Client然後可以使用IBind提供的方法來使用Service。
- onCreate() Service第一次建立時被調用,和Activity的onCreate類似。
- onDestroy() Service退出時調用。
定義了Service類和實現相應方法後,和Activity一樣,也需要在AndroidManifest.xml中定義這個Service:
<manifest … >…<application … ><service android:name=”.ExampleService” />…< /application>< /manifest>
和Activity一樣,也可以為Service定義Intent Filter,如果你不想共用這個Service,可以將android:exported屬性定義為false。
通常情況下Service在後台運行,當Android也支援Service運行在前台,運行在前台的Service必須在螢幕頂端的Status Bar提供一個Notification以提示使用者有Service在運行。比如提供個Media Player使用的Service運行在前台,而在標題列顯示當前曲目。
本例Foreground Service Controller就顯示了一個在前台啟動並執行Service, 前台啟動並執行Service可以通過調用startForeground()使Service在前台運行。stopForeground停止前台運行,但 Service本身不會停止。 startForeground,stopForeground是從2.0開始支援的,之前的版本採用setForeground。
本例為了支援2.0之前和2.0之後的版本,採用了Reflection的方法來來尋找目前的版本是否含有startForeground和stopForeground,如果有則調用,沒有則還是使用setForeground。
如果找到的話,以下的變數用來儲存startForeground和stopForeground方法。和本例Service不相關,就不詳述了。 只要知道startForegroundCompat 和stopForegroundCompat的功能就是startForeground 和stopForeground就行了。
private static final Class[] mStartForegroundSignature = new Class[] { int.class, Notification.class};private static final Class[] mStopForegroundSignature = new Class[] { boolean.class}; private Method mStartForeground;private Method mStopForeground;private Object[] mStartForegroundArgs = new Object[2];private Object[] mStopForegroundArgs = new Object[1];
下面來看看ForegroundService的代碼:
首先是必須作為Service的子類:
public class ForegroundService extends Service
因為是作為“Started” Service來設計的,因此需定義onStartCommand ,同樣onStartCommand也是在Android 2.0之後添加的,2.0之前為onStart。本例為了支援所有版本,兩個方法對實現了,對應2.0之後的版本,只會調用 onStartCommand,2.0之前的只會調用onStart:
// This is the old onStart method that// will be called on the pre-2.0 platform.// On 2.0 or later we override onStartCommand() so this// method will not be called.@Overridepublic void onStart(Intent intent, int startId) {handleCommand(intent);} @Overridepublic int onStartCommand(Intent intent, int flags, int startId) {handleCommand(intent);// We want this service to//continue running until it is explicitly// stopped, so return sticky.return START_STICKY;}
onStartCommand 可以有返回結果,這個傳回值告訴Android系統當這個Service被Kill之後(比如當系統記憶體不足時)後續操作。START_STICKY 表示系統Kill這個Service之後,如果重新建立這個Service時在調用onStartCommand ,不會將最後的Intent作為參數傳入,也就是說intent=null. START_REDELIVER_INTENT則會傳入被殺前未處理的最後一個Intent。
本Service不作為Bind Service ,因此通過一個空實現:
@Overridepublic IBinder onBind(Intent intent) { return null;}
最後看看如何啟動/停止這個Service, Controller 是作為這個Service的控制類來實現的,提供了前台啟動,後台啟動,和停止Service操作:
private OnClickListener mForegroundListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(ForegroundService.ACTION_FOREGROUND); intent.setClass(Controller.this, ForegroundService.class); startService(intent); }}; private OnClickListener mBackgroundListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(ForegroundService.ACTION_BACKGROUND); intent.setClass(Controller.this, ForegroundService.class); startService(intent); }}; private OnClickListener mStopListener = new OnClickListener() { public void onClick(View v) { stopService(new Intent(Controller.this, ForegroundService.class)); }};
【起航計劃 033】2015 起航計劃 Android APIDemo的魔鬼步伐 32 App->Service->Foreground Service Controller service使用,共用service,前台服務,onStartCommand