原文:Xamarin.Android開發實踐(五)html
服務與活動同樣,在它的整個生命週期中存在着一些事件,下圖能夠很好解釋整個過程以及涉及到的方法:android
在真實的使用中,Service來還包含一個OnBind方法,而且必需要使用該方法,可是隻要返回NULL便可,除非當前服務是一個綁定服務,那麼就要返回實現了IBinder的實例。ide
上圖中涉及到了幾個方法,下面將作簡單的介紹:post
OnCreate:只會在服務第一次開啓的時候調用,主要負責一些初始化代碼測試
OnStartCommand:每次啓動服務都會調用該方法,可能來自StartService或者由系統重啓。通常負責開啓須要長時間的任務。而且該方法還要返回StartCommandResult類型的枚舉,該返回值將影響系統重啓該服務的細節。this
OnDestroy:當服務使用StopSelf或者StopService時調用,主要用來釋放資源等。url
Sticky:當服務因爲內存不夠被系統關閉後,將會由系統重啓該服務,可是傳入OnStartCommand方法的intent參數爲NULL,意味着該類型的服務沒法恢復上次的狀態,只能進行常規的長時間任務。spa
RedeliverIntent:該類型的服務與Sticky的惟一的區別就是在系統重啓該服務時,將會將上次關閉的服務的狀態傳遞給OnStartCommand方法,用來恢復上次的任務繼續執行。適合須要長時間連續的任務。線程
NotSticky:該服務被系統關閉後將不會重啓。3d
StickyCompatibility:在API 5或以上的環境中的行爲與Sticky同樣,相反在API 5如下可能不會重啓服務。
這裏咱們須要繼承自Service並還要須要加上Service註解屬性(項目自行新建)
1 namespace ServiceStudy 2 { 3 [Service] 4 public class MainService : Service 5 { 6 7 } 8 }
其中[Service]負責在AndroidManifest.xml註冊服務,好比上面的服務將會生成以下字符串:
1 <service android:name="ServiceStudy.MainService"></service>
下面咱們開始具體實現一個服務,上面已經說明了不管任何服務都要重寫OnBind方法,因此咱們先重寫該方法:
1 public override Android.OS.IBinder OnBind(Android.Content.Intent intent) 2 { 3 return null; 4 }
而後是OnCreate方法:
1 public override void OnCreate() 2 { 3 base.OnCreate(); 4 Log.Debug("xamarin", "建立服務"); 5 }
接着是OnStartCommand方法:
1 public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId) 2 { 3 Log.Debug("xamarin", "啓動服務"); 4 return StartCommandResult.Sticky; 5 }
最後就是OnDestroy方法:
1 public override void OnDestroy() 2 { 3 base.OnDestroy(); 4 Log.Debug("xamarin", "關閉服務"); 5 }
這樣一個簡單的服務就完成了,下面是總體代碼:
1 [Service] 2 public class MainService : Service 3 { 4 public override void OnCreate() 5 { 6 base.OnCreate(); 7 Log.Debug("xamarin", "建立服務"); 8 } 9 10 public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId) 11 { 12 Log.Debug("xamarin", "啓動服務"); 13 return StartCommandResult.Sticky; 14 } 15 16 public override void OnDestroy() 17 { 18 base.OnDestroy(); 19 Log.Debug("xamarin", "關閉服務"); 20 } 21 22 public override Android.OS.IBinder OnBind(Android.Content.Intent intent) 23 { 24 return null; 25 } 26 }
有了上面的服務咱們如今就能夠開啓它了,開啓服務的方法以下:
1 StartService(new Intent(this, typeof(MainService)));
中止服務的方法以下:
1 StopService(new Intent(this, typeof(MainService)));
首先打開Main.axml,再拖拽一個按鈕進去,並設置他們的Text,以及id爲@+id/startButton和@+id/stopButton,結果以下:
接着打開MainActivity.cs文件,爲這兩個按鈕綁定監聽事件:
1 public class MainActivity : Activity 2 { 3 protected override void OnCreate(Bundle bundle) 4 { 5 base.OnCreate(bundle); 6 SetContentView(Resource.Layout.Main); 7 Button startButton = FindViewById<Button>(Resource.Id.startButton); 8 Button stopButton = FindViewById<Button>(Resource.Id.stopButton); 9 10 startButton.Click += delegate 11 { 12 StartService(new Intent(this, typeof(MainService))); 13 }; 14 15 stopButton.Click += delegate 16 { 17 StopService(new Intent(this, typeof(MainService))); 18 }; 19 } 20 }
最終在模擬機上進行測試,得出下面的結果:
從中能夠看到多個連續的啓動服務,由於筆者按下了返回退出了應用,而後再返回到應用中,開啓服務,那麼就只顯示啓動服務了,而不會通過建立服務了。
經過上面的例子,你們必定有人不停的開啓服務。固然每次開啓的都是一個新的服務。可是關閉服務的時候並非關閉其中一個,而是把全部的服務都關閉了。由這個就須要考慮一種狀況,就是如何區分不一樣的實例以及關閉不一樣的實例呢?
你們能夠看看
服務中已經提供了專門的方法,固然若是是關閉當前的服務能夠直接用StopSelf(),下面咱們將OnStartCommand中重寫,開啓一個線程:
1 public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId) 2 { 3 Log.Debug("xamarin", "啓動服務"); 4 new Thread(() => 5 { 6 Log.Debug("xamarin", startId + "號服務的線程啓動"); 7 Thread.Sleep(1000); 8 Log.Debug("xamarin", startId + "號服務的線程關閉"); 9 StopSelf(startId); 10 }).Start(); 11 return StartCommandResult.Sticky; 12 }
咱們這裏使用了StopSelft的重載版本關閉了服務。
而後咱們再開始進行調試,首先咱們按下一次開啓服務,將出現以下的結果:
接着咱們快速的點擊兩次開啓服務,將出現以下的結果:
經過這張圖咱們能夠看到,輸出了1號和2號,同時在完成執行後,咱們再點關閉服務就沒有任何反應了,由於服務本身已經把本身關閉了。
上面全部的服務開啓方法都是經過類型開啓的,可是這樣的缺點顯而易見,若是咱們改變了服務的名稱就須要改正其餘的地方,而經過這節咱們將可使用字符串名稱來開啓服務。
這裏咱們須要使用IntentFilter註解屬性,好比下面這樣的註解屬性:
則會在AndroidManifest.xml中生成以下的字符串:
1 <service android:name="ServiceStudy. MainService"> 2 <intent-filter> 3 <action android:name="xamarin-cn.com.mainservice" /> 4 </intent-filter> 5 </service>
咱們先給MainService加上Intent Filter:
1 [Service] 2 [IntentFilter(new string[]{"xamarin-cn.com.mainservice"})] 3 public class MainService : Service
而後修改開啓服務地方的代碼:
1 protected override void OnCreate(Bundle bundle) 2 { 3 base.OnCreate(bundle); 4 SetContentView(Resource.Layout.Main); 5 Button startButton = FindViewById<Button>(Resource.Id.startButton); 6 Button stopButton = FindViewById<Button>(Resource.Id.stopButton); 7 8 startButton.Click += delegate 9 { 10 StartService(new Intent("xamarin-cn.com.mainservice")); 11 }; 12 13 stopButton.Click += delegate 14 { 15 StopService(new Intent("xamarin-cn.com.mainservice")); 16 }; 17 }
這裏咱們依然仍是使用Intent可是傳遞的參數已經變成了字符串。