原文: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 }

五、启用与停止服务

有了上面的服务我们现在就可以开启它了,开启服务的方法如下:

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 }

最终在模拟机上进行测试,得出下面的结果:

从中可以看到多个连续的启动服务,因为笔者按下了返回退出了应用,然后再返回到应用中,开启服务,那么就只显示启动服务了,而不会经过创建服务了。

六、使用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 }

我们这里使用了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 }

这里我们依然还是使用Intent但是传递的参数已经变成了字符串。

Xamarin.Android开发实践(五)的更多相关文章

  1. Xamarin.Android开发实践(四)

    原文:Xamarin.Android开发实践(四) Xamarin.Android下获取与解析JSON 一.新建项目 1.新建一个Android项目,并命名为为NetJsonList 2.右击引用,选 ...

  2. Xamarin.Android开发实践(二)

    原文:Xamarin.Android开发实践(二) 一.准备 开始学习本教程前必须先完成该教程http://www.cnblogs.com/yaozhenfa/p/xamarin_android_qu ...

  3. Xamarin.Android开发实践(三)

    原文:Xamarin.Android开发实践(三) 一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没 ...

  4. Xamarin.Android开发实践(一)

    原文:Xamarin.Android开发实践(一) 一.准备工作 1.创建一个空的解决方案,并命名为Phoneword 2.右击解决方案 新建->新建项目 并命名为Phoneword_Droid ...

  5. Xamarin.Android开发实践(十五)

    Xamarin.Android学习之应用程序首选项 一.前言 任何App都会存在设置界面,如果开发者利用普通控件并绑定监听事件保存设置,这 一过程会非常的枯燥,而且耗时.我们可以看到Android系统 ...

  6. Xamarin.Android开发实践(十七)

    Xamarin.Android之定位 一.前言 打开我们手中的应用,可以发现越来越多的应用使用了定位,从而使我们的生活更加方便,所以本章我们将学习如何在Xamarin中进行定位的开发. 二.准备工作 ...

  7. Xamarin.Android开发实践(十四)

    Xamarin.Android之ListView和Adapter 一.前言 如今不管任何应用都能够看到列表的存在,而本章我们将学习如何使用Xamarin去实现它,以及如何使用适配器和自定义适配器(本文 ...

  8. Xamarin.Android开发实践(十一)

    Xamarin.Android之使用百度地图起始篇 一.前言 如今跨平台开发层出不穷,而对于.NET而言时下最流行的当然还是 Xamarin,不仅仅能够让我们在熟悉的Vs下利用C#开发,在对原生态类库 ...

  9. Xamarin.Android开发实践(九)

    Xamarin.Android之ActionBar与菜单 一.选项卡 如今很多应用都会使用碎片以便在同一个活动中能够显示多个不同的视图.在 Android 3.0 以上的版本中,我们已经可以使用Act ...

随机推荐

  1. Apple Catching(dp)

    Apple Catching Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9831   Accepted: 4779 De ...

  2. 迷宫城堡(强联通targin)

    迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  3. 180行ruby代码搞定游戏2048

    最今在玩2048这款小游戏,游戏逻辑简单,很适合我这样的对于游戏新入行的人来实现逻辑.于是选择了最拿手的ruby语言来实现这款小游戏的主要逻辑.还是挺简单的,加起来4小时左右搞定. 上代码: requ ...

  4. Core Data Stack学习笔记

    Entity Entities 实体->数据表一个实体可以表示一个数据模型 1> 通过图形化界面可以建立一个模型关系图,可以指定一对多,多对一,多对多的数据关系 -在数据库开发中,少用多对 ...

  5. 【JS控制图片显示的大小(图片等比例缩放)】

    效果: 代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...

  6. iOS 中UITableViewController 中tableView 会被状态栏覆盖的问题

    解决办法在 生命周期函数viewDidAppear中设置即可 - (void)viewDidAppear:(BOOL)animated { self.tableView.frame = CGRectM ...

  7. JavaScriptCore.framework基本用法(二)

    接着上节我们讲到的iOS调用js 下来我们使用js调用iOS js调用iOS分两种情况 一,js里面直接调用方法 二,js里面通过对象调用方法 首先我们看第一种,直接调用方法. 其中用到了iOS的bl ...

  8. JavaSE复习日记 : 算是个小前言吧

    /* * Java也学了好久了,抽个时间整理了一下课堂笔记,也有些是我刚开始学会犯的一些错误.在这里浅谈一下JavaSE的基础内容,对我来说也是一种不错的复习方式. * * 那好,对于初学者来说,学习 ...

  9. mysql中随机取出几条数据

    SELECT t1.id,title,extName,cover,url FROM shop_articles AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT M ...

  10. C#获取上个月的第一天零点和最后一天23点59分59秒

    //上个月第一天0点 DateTime date2 = DateTime.Now.AddMonths(-1).Date.AddDays(1 - DateTime.Now.Day);         R ...