簡介
Service為Android上提供用來做背景服務用的應用程式架構。簡單來說就是一個在背景執行的程式,該程式不需要和使用者互動,所以也不會有操作介面。更重要的是,它的生命週期是和Activity各自分開的,Activity就算關閉了,Service 仍然可以繼續執行。
Service通常用來執行重覆性的事(例如每隔一段時間檢查是否有更新資料),或者需要執行很久的事情上(例如在背景從網路上下載檔案)。
Service的兩種模式
Started模式
當Service一旦透過Context.startService()
啟動後,這個Service就可以無限的在系統背後執行,即使啟動這個Service的Activity或應用程式被關閉,這個Service仍可以繼續執行本身的工作。但一般來說,Service並不會和啟動它的應用程式有什麼互動,Service完成後也不會回傳或通知原本啟動它的應用程式。所以如果一旦Service執行完成,Service就會自動停止。
Bind模式
Service另一個功能就是負責跨Process(應用程式行程)的功能協作。各個不同的應用程式可以透過Context.bindService()
的方法來使用此應用程式在Service裡所提供的功能,以達到兩個應用程式的互動。也就是Service在bind之後可以如同在同一個程式內直接去呼叫Service內的方法來使用。
一個Service可以被多個不同的應用程式透過Context.bindService()
的方式綁定。只要有其它應用程式開始綁定這個Service,這個Service就會啟動。一直到所有的應用程式都不再使用這個Service,這個Service就會自動被銷毀。
備註:
以上兩種形式其實並不衝突, 一個服務可以透過
當在startService()
的方式被啟動,然後再被其它應用程式綁定。只要同時實作onStartCommand()
與onBind()
兩個事件即可。AndroidManifest.xml
檔中將Service宣告成android:exported=”false”
時,其它應用程式就不能啟動這個Service了。
Service生命週期

一個Service可以被系統啟動的原因有兩種
- 當有應用程式呼叫
Context.startService()
方法時,系統會呼叫Service物件內的onCreate()
方法,接下來會呼叫onStartCommand()
方法讓應用程式端提供參數來決定做哪些事情。一直到Context.stopService()
方法被呼叫,或者是Service內自己呼叫stopSelf()
方法才會停止。 - 另一個被啟動的方式是有其它的應用程式端透過
Context.bindService()
來取得與Service的連結。如果該Service不在啟動狀態的話,這種方式則會啟動這個Service.onCreate()
的方式這時就會被呼叫,但這種方式並不會觸發onStartCommand()
事件。啟動這個Service的應用程式會透過onBind()
方法取得IBinder
物件。接下來就可以透過IBinder
物件來取得Service的事件(透過callback的方法)。只要連線不被中斷,Service就會保持執行狀態。
Service可以同時支援Started與Bind兩種模式。在這種情況下,Service會持續運作到被Started模式關閉,同時Bind模式中已經沒有任何連線時才會結束,結束時會觸發onDestroy()
事件。
Service的運作優先權相當的高,一般來說除非系統資源耗盡,否則Android不會主動關閉一個已被啟動的Service。一旦系統有足夠的資源,被Android關閉的Service也會被重新啟動。
因為Service和應用程式預設是執行在同一個Process(應用程式行程)的主執行緒中,所以如果在Service中執行了耗時的工作,連帶的也會影響到應用程式的反應。
一般來說很少需要特別指定另一個Process來執行Service,除非這個Service會對其它應用程式提供服務時才需要。
建立Service(Started模式)
建立Started模式的Service需要三個步驟:在AndroidManifest.xml檔中新增定義
<service android:name=”” android:enabled=”true />
這裡的
android:name
是你自訂的Service類別的完整名稱。實作一個繼承自
android.app.Service
類別的物件public class MyService extends Service { int mStartMode; // indicates how to behave if the service is killed IBinder mBinder; // interface for clients that bind boolean mAllowRebind; // indicates whether onRebind should be used @Override public void onCreate() { // The service is being created } @Override public int onStartCommand(Intent intent, int flags, int startId) { // The service is starting, due to a call to startService() return mStartMode; } @Override public IBinder onBind(Intent intent) { // A client is binding to the service with bindService() return mBinder; } @Override public boolean onUnbind(Intent intent) { // All clients have unbound with unbindService() return mAllowRebind; } @Override public void onRebind(Intent intent) { // A client is binding to the service with bindService(), after onUnbind() has already been called } @Override public void onDestroy() { // The service is no longer used and is being destroyed } }
在
常數值分別為:onStartCommand()
中,最後需要回傳一個常數,這些常數定義在Service類別中。該回傳值是用在如果這個Service被Android作業系統終止後的行為。Service.START_STICKY Service如果被中止的話會自動重啟。用在onStartCommand()方法中不需要依賴Intent傳入的資料就可以執行的時候(重新啟動時重新傳入的Intent會是null)。這也是預設使用super.onStartCommnad()的回傳值。 Service.START_NOT_STICKY Servcie如果被中止的話不重新啟動,用在onStartCommand()方法中所執行的工作需要依賴Intent物件內帶進來的參數。 Service.START_REDELIVER_INTENT 和START_STICKY差不多,但Android會在中止Service之前將Intent保留下來,等待重新啟動時再將原本的Intent物件交還給onStartCommand()事件。 public class MyService extends Service { public IBinder onBind(Intent intent) @Override { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { //這裡實作你想做的工作 return Service.START_STICKY; } }
- 在Activity中呼叫
startService()
來執行@Override public View onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); super.onCreate(savedInstanceState); Intent intent = new Intent(this, MyService.class); this.startService(intent); }
以上三個步驟就可以啟動一個Started模式的Service。
建立Service(Bind模式)
另外一種啟動Service的方式,透過Bind方式來啟動Service。在AndroidManifest.xml檔中新增定義
<service android:name=”” android:enabled=”true />
這裡的
android:name
是你自訂的Service類別的完整名稱。實作onBind(Intent) 事件。IBinder 介面負責應用程式端與Service端的溝通,用來將Service的實體透過Binder的延伸方法的方式取得。
public class MyService extends Service { private final IBinder mBinder = new MyBinder(); private String info = ""; @Override public IBinder onBind(Intent intent) { return mBinder; } public class MyBinder extends Binder { MyService getService() { return MyService.this; } } public String getInfo() { return info; } }
在應用程式端(例如Activity內)實作
ServiceConnection
介面private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder binder) { // 取出Service實體 service = ((MyService.MyBinder)binder).getService(); } @Override public void onServiceDisconnected(ComponentName className) { service = null; } }
在啟動該Service的Activity中,可以在
onResume()
與onStop()
的事件中管理與Service的連線public class MainActivity extends Activity { @Override public void onResume() { Intent intent = new Intent(this, MyService.class); super.onResume(); this.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } @Override public void onPause() { super.onPause(); this.unbindService(mServiceConnection); } }