一、服务的生命周期

服务与活动一样,在它的整个生命周期中存在着一些事件,下图可以很好解释整个过程以及涉及到的方法:

在真实的使用中,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注解属性(项目自行新建)

[Service]
    public class MainService : Service
    {
        public override void OnCreate()
        {
            base.OnCreate();
            Log.Debug("xamarin", "创建服务");
        }


        public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
        {
            Log.Debug("xamarin", "启动服务");
            return StartCommandResult.Sticky;
        }


        public override void OnDestroy()
        {
            base.OnDestroy();
            Log.Debug("xamarin", "关闭服务");
        }


        public override Android.OS.IBinder OnBind(Android.Content.Intent intent)
        {
            return null;
        }
}

五、启用与停止服务

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

StartService(new Intent(this, typeof(MainService)));

停止服务的方法如下:

StopService(new Intent(this, typeof(MainService)));

首先打开Main.axml,再拖拽一个按钮进去,并设置他们的Text,以及id为@+id/startButton和@+id/stopButton,接着打开MainActivity.cs文件,为这两个按钮绑定监听事件。

public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Main);
            Button startButton = FindViewById<Button>(Resource.Id.startButton);
            Button stopButton = FindViewById<Button>(Resource.Id.stopButton);


            startButton.Click += delegate
            {
                StartService(new Intent(this, typeof(MainService)));
            };


            stopButton.Click += delegate
            {
                StopService(new Intent(this, typeof(MainService)));
            };
        }
}

六、使用startId关闭服务

通过上面的例子,大家一定有人不停的开启服务。当然每次开启的都是一个新的服务。但是关闭服务的时候并不是关闭其中一个,而是把所有的服务都关闭了。由这个就需要考虑一种情况,就是如何区分不同的实例以及关闭不同的实例呢?

大家可以看看 服务中已经提供了专门的方法,当然如果是关闭当前的服务可以直接用StopSelf(),下面我们将OnStartCommand中重写,开启一个线程:

public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
        {
            Log.Debug("xamarin", "启动服务");
            new Thread(() =>
            {
                Log.Debug("xamarin", startId + "号服务的线程启动");
                Thread.Sleep(1000);
                Log.Debug("xamarin", startId + "号服务的线程关闭");
                StopSelf(startId);
            }).Start();
            return StartCommandResult.Sticky;
        }

我们这里使用了StopSelft的重载版本关闭了服务。

七、通过Intent Filter开启服务

上面所有的服务开启方法都是通过类型开启的,但是这样的缺点显而易见,如果我们改变了服务的名称就需要改正其他的地方,而通过这节我们将可以使用字符串名称来开启服务。

我们先给MainService加上Intent Filter:

 [Service]

[IntentFilter(new string[]{"xamarin-cn.com.mainservice"})]

public class MainService : Service

然后修改开启服务地方的代码:

protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Main);
            Button startButton = FindViewById<Button>(Resource.Id.startButton);
            Button stopButton = FindViewById<Button>(Resource.Id.stopButton);




            startButton.Click += delegate
            {
                StartService(new Intent("xamarin-cn.com.mainservice"));
            };




            stopButton.Click += delegate
            {
                StopService(new Intent("xamarin-cn.com.mainservice"));
            };
        }