Xamarin.Android服務的實現


一、服務的生命周期

服務與活動一樣,在它的整個生命周期中存在着一些事件,下圖可以很好解釋整個過程以及涉及到的方法:

在真實的使用中,Service來還包含一個OnBind方法,並且必須要使用該方法,但是只要返回NULL即可,除非當前服務是一個綁定服務,那么就要返回實現了IBinder的實例。

 

二、回調方法的總結

上圖中涉及到了幾個方法,下面將做簡單的介紹:

OnCreate:只會在服務第一次開啟的時候調用,主要負責一些初始化代碼

OnStartCommand:每次啟動服務都會調用該方法,可能來自StartService或者由系統重啟。一般負責開啟需要長時間的任務。並且該方法還要返回StartCommandResult類型的枚舉,該返回值將影響系統重啟該服務的細節。

OnDestroy:當服務使用StopSelf或者StopService時調用,主要用來釋放資源等。

 

三、返回不同StartCommandResult服務的區別

Sticky:當服務由於內存不夠被系統關閉后,將會由系統重啟該服務,但是傳入OnStartCommand方法的intent參數為NULL,意味着該類型的服務無法恢復上次的狀態,只能進行常規的長時間任務。

RedeliverIntent:該類型的服務與Sticky的唯一的區別就是在系統重啟該服務時,將會將上次關閉的服務的狀態傳遞給OnStartCommand方法,用來恢復上次的任務繼續執行。適合需要長時間連續的任務。

NotSticky:該服務被系統關閉后將不會重啟。

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 }
View Code

 

 

五、啟用與停止服務

有了上面的服務我們現在就可以開啟它了,開啟服務的方法如下:

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 }
View Code

 

 最終在模擬機上進行測試,得出下面的結果:

 從中可以看到多個連續的啟動服務,因為筆者按下了返回退出了應用,然后再返回到應用中,開啟服務,那么就只顯示啟動服務了,而不會經過創建服務了。

 

六、使用startId關閉服務

通過上面的例子,大家一定有人不停的開啟服務。當然每次開啟的都是一個新的服務。但是關閉服務的時候並不是關閉其中一個,而是把所有的服務都關閉了。由這個就需要考慮一種情況,就是如何區分不同的實例以及關閉不同的實例呢?

 

大家可以看看

 服務中已經提供了專門的方法,當然如果是關閉當前的服務可以直接用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         }
View Code

我們這里使用了StopSelft的重載版本關閉了服務。

 

然后我們再開始進行調試,首先我們按下一次開啟服務,將出現如下的結果:

 

接着我們快速的點擊兩次開啟服務,將出現如下的結果:

 

通過這張圖我們可以看到,輸出了1號和2號,同時在完成執行后,我們再點關閉服務就沒有任何反應了,因為服務自己已經把自己關閉了。

 

七、通過Intent Filter開啟服務

上面所有的服務開啟方法都是通過類型開啟的,但是這樣的缺點顯而易見,如果我們改變了服務的名稱就需要改正其他的地方,而通過這節我們將可以使用字符串名稱來開啟服務。

這里我們需要使用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         }
View Code

 

這里我們依然還是使用Intent但是傳遞的參數已經變成了字符串。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM