《Android》『Service』- 背景執行服務的基本用法
《Android Developers 參考文獻》
《繼承架構》
extends ContextWrapper
implements ComponentCallbacks2
↳ android.content.ContextWrapper
↳ android.app.Service
《簡單介紹》
Service 從字面來看是『服務』的意思,在 Android 中,它是一個在背景執行的服務,可以把它想成是 Android 中特有的一種 Thread 形式,主要用於在背景執行一些耗時的邏輯運算。
《用法介紹》
Service 本身沒有介面,用法類似 BroadcastReceiver,需要定義一個繼承 Service 的類別,並覆寫其中的生命週期函數,最後在 AndroidManifest.xml 中宣告才能使用,Service 可以被自己與其他的 App 存取,當一個 App 要使用別人的 Service 時,是在它自己 App 的 AndroidManifest.xml 中的 uses-permission 作宣告。
Service 的生命週期
上圖為 Service 的生命週期,根據執行方式的不同分為兩種,分別說明如下 –
startService(intent)
透過 startService(intent) 啟動 Service,系統會先執行 onCreate(),然後將所傳進來的 intent 帶入 Service 的 onStartCommand(Intent, int, int)中,這個 Service 會一直執行,直到有人呼叫 stopService() 或內部呼叫 stopSelf() 才會停止。無論 startService() 被呼叫了多少次,只要執行一次 stopService(),或在 Service 內執行 stopSelf(),就會被停止(第一次啟動 Service 時才會執行 onCreate())。
生命週期 : onCreate() ➞ onStartCommand() ➞ onDestroy()
※利用 startService(intent) 啟動 Service,開啟後此 Service 便與調用者沒有任何的關係,也就是說,調用該服務的 activity 即便是退出了也不會影響 Service 的運行。而從 activity 亦不能去調用 Service 裡面的方法 。
bindService(intent, ServiceConnection, int flags)
2. 透過 bindService(intent, mServiceConnection, int flags) 建立一個與 Service 綁定的連線,首先我們必須先建立一個 serviceConnection 物件,把這物件當作參數放到 bindService 內,flags 參數預設 BIND_AUTO_CREATE,也就是當我們綁定的時候會自動產生 Service。
生命週期 : onCreate() ➞ onBind() ➞ onUnbind() ➞ onDestroy()
※利用 bindService(intent, ServiceConnection, int flags) 啟動 Service,開啟後此 Service 便與調用者一起存活或是退出,也就是說,調用該服務的 activity 一退出, Service 的運行也會一起終止。而從 activity 可以透過 IBinder 物件取得 Service 物件,直接操作 Service 內各個 public 的 method。
程式實作
以下直接透過程式碼片段,說明建立 Service 的兩種方式。
Step 1 – 自訂一個繼承 Service 的類別
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
package ... import android.app.Service; import ... public class MyService extends Service { public class LocalBinder extends Binder //宣告一個繼承 Binder 的類別 LocalBinder { MyService getService() { return MyService.this; } } private LocalBinder mLocBin = new LocalBinder(); public void myMethod() { Log.d(LOG_TAG, "myMethod()"); } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return mLocBin; } @Override public void onCreate() { super.onCreate(); // TODO Auto-generated method stub } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); // TODO Auto-generated method stub } } |
MyService.java
我們先宣告一個繼承 Service 的類別,自訂其名稱為 MyService,並覆寫由 Service 所提供的各種生命週期函數。
onBind() : 綁定服務
onUnBind() : 解除綁定服務
onCreate() : 建立服務
onDestroy() : 銷毀服務
onStartCommand() : 啟動服務
onStart() : 啟動服務 (android2.0 以下版本適用)
Step 2 – 於 AndroidManifest.xml 中宣告此自訂 Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"...> <uses-sdk android:targetSdkVersion="11" /> <application ...> <activity ...> <intent-filter> ... </intent-filter> </activity> <service android:name=".MyService" android:enabled="true" /> </application> </manifest> |
AndroidManifest.xml
接著,我們必須在 AndroidManifest.xml 中宣告 MyService。
Step 3 – 於 Activity 中調用自訂的 Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
package ... import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import ... public class MainActivity extends Activity { private MyService mMyService = null; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder serviceBinder) { // TODO Auto-generated method stub mMyService = ((MyService.LocalBinder)serviceBinder).getService(); } public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub Log.d(LOG_TAG, "onServiceDisconnected()" + name.getClassName()); } }; private Button mBtnStartMyService, mBtnStopMyService, mBtnBindMyService, mBtnUnbindMyService, mBtnCallMyServiceMethod; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mBtnStartMyService = (Button) findViewById(R.id.btnStartMyService); mBtnStopMyService = (Button) findViewById(R.id.btnStopMyService); mBtnBindMyService = (Button) findViewById(R.id.btnBindMyService); mBtnUnbindMyService = (Button) findViewById(R.id.btnUnbindMyService); mBtnCallMyServiceMethod = (Button) findViewById(R.id.btnCallMyServiceMethod); mBtnStartMyService.setOnClickListener(btnStartMyServiceOnClkLis); mBtnStopMyService.setOnClickListener(btnStopMyServiceOnClkLis); mBtnBindMyService.setOnClickListener(btnBindMyServiceOnClkLis); mBtnUnbindMyService.setOnClickListener(btnUnbindMyServiceOnClkLis); mBtnCallMyServiceMethod.setOnClickListener(btnCallMyServiceMethodOnClkLis); } private OnClickListener btnStartMyServiceOnClkLis = new OnClickListener() { public void onClick(View v) { mMyService = null; Intent it = new Intent(Main.this, MyService.class); startService(it); //開始Service } }; private OnClickListener btnStopMyServiceOnClkLis = new OnClickListener() { public void onClick(View v) { mMyService = null; Intent it = new Intent(Main.this, MyService.class); stopService(it); //結束Service } }; private OnClickListener btnBindMyServiceOnClkLis = new OnClickListener() { public void onClick(View v) { mMyService = null; Intent it = new Intent(Main.this, MyService.class); bindService(it, mServiceConnection, BIND_AUTO_CREATE); //綁定Service } }; private OnClickListener btnUnbindMyServiceOnClkLis = new OnClickListener() { public void onClick(View v) { mMyService = null; unbindService(mServiceConnection); //解除綁定Service } }; private OnClickListener btnCallMyServiceMethodOnClkLis = new OnClickListener() { public void onClick(View v) { if (mMyService != null) mMyService.myMethod(); //透過bindService()可以使用Service中的方法 } }; } |
MainActivity.java
在 MainActivity 中,我們定義了五個按鈕,分別執行 startService()、stopService()、bindService()、unbindService() 以及執行 Service 中定義的方法之動作。並且定義了在 bindService() 中,會用到的 mServiceConnection 物件,當 Service 綁定成功後,會自動呼叫執行這個mServiceConnection 內的 onServiceConnected(ComponentName className, IBinder service) 函式,此函式會接收到由 Service 內的onBind() 所丟出來的 Ibinder 物件,利用這 IBinder 物件取得 Service 物件,就可以直接操作 Service 內各個 public 的 method。
臉書留言
一般留言