【起航計劃 033】2015 起航計劃 Android APIDemo的魔鬼步伐 32 App->Service->Foreground Service Controller service使用,共享

Android系統也提供了一種稱爲「Service」的組件一般在後臺運行。Activity 能夠用來啓動一個Service,Service啓動後能夠保持在後臺一直運行,即便啓動它的Activity退出或是切換到別的應用Service也能保持運行狀態。android

Service 能夠以兩種形式存在:app

  • 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能夠同時以兩種方式存在,只要實現兩種方法所定義的接口函數就能夠了。ide

建立一個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:this

<manifest … ><application … >
<service android:name=」.ExampleService」 />< /application>
< /manifest>

和Activity同樣,也能夠爲Service定義Intent Filter,若是你不想共享這個Service,能夠將android:exported屬性定義爲false。spa

一般狀況下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。code

本例爲了支持2.0以前和2.0以後的版本,採用了Reflection的方法來來查找當前版本是否含有startForeground和stopForeground,若是有則調用,沒有則仍是使用setForeground。orm

若是找到的話,如下的變量用來存儲startForeground和stopForeground方法。和本例Service不相關,就不詳述了。 只要知道startForegroundCompat 和stopForegroundCompat的功能就是startForeground 和stopForeground就好了。xml

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.
@Override
public void onStart(Intent intent, int startId) {
handleCommand(intent);
}
 
@Override
public 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 ,所以經過一個空實現:

@Override
public 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));
 }
};

 

 

相關文章
相關標籤/搜索