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注解属性(项目自行新建)
namespace ServiceStudy
{
[Service]
public class MainService : Service
{ }
}
其中[Service]负责在AndroidManifest.xml注册服务,比如上面的服务将会生成如下字符串:
<service android:name="ServiceStudy.MainService"></service>
下面我们开始具体实现一个服务,上面已经说明了无论任何服务都要重写OnBind方法,所以我们先重写该方法:
public override Android.OS.IBinder OnBind(Android.Content.Intent intent)
{
return null;
}
然后是OnCreate方法:
public override void OnCreate()
{
base.OnCreate();
Log.Debug("xamarin", "创建服务");
}
接着是OnStartCommand方法:
public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
{
Log.Debug("xamarin", "启动服务");
return StartCommandResult.Sticky;
}
最后就是OnDestroy方法:
public override void OnDestroy()
{
base.OnDestroy();
Log.Debug("xamarin", "关闭服务");
}
这样一个简单的服务就完成了,下面是整体代码:
[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();
Log.Debug("xamarin", startId + "号服务的线程关闭");
StopSelf(startId);
}).Start();
return StartCommandResult.Sticky;
}
我们这里使用了StopSelft的重载版本关闭了服务。
然后我们再开始进行调试,首先我们按下一次开启服务,将出现如下的结果:

接着我们快速的点击两次开启服务,将出现如下的结果:

通过这张图我们可以看到,输出了1号和2号,同时在完成执行后,我们再点关闭服务就没有任何反应了,因为服务自己已经把自己关闭了。
七、通过Intent Filter开启服务
上面所有的服务开启方法都是通过类型开启的,但是这样的缺点显而易见,如果我们改变了服务的名称就需要改正其他的地方,而通过这节我们将可以使用字符串名称来开启服务。
这里我们需要使用IntentFilter注解属性,比如下面这样的注解属性:

则会在AndroidManifest.xml中生成如下的字符串:
<service android:name="ServiceStudy. MainService">
<intent-filter>
<action android:name="xamarin-cn.com.mainservice" />
</intent-filter>
</service>
我们先给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"));
};
}
这里我们依然还是使用Intent但是传递的参数已经变成了字符串。
Xamarin.Android服务的实现的更多相关文章
- [译]:Xamarin.Android平台功能——位置服务
返回索引目录 原文链接:Location Services. 译文链接:Xamarin.Android平台功能--位置服务 本部分介绍位置服务以及与如何使用位置提供商服务 Location Servi ...
- Xamarin.Android其他类型的服务
一.前言 前面我们已经学了关于服务的很多知识,但是对于真实的开发那些远远不够,通过这节我们将学习其他类型的服务,比如前台服务.IntentService和消息服务.下面我们开始进入正题. 二.前台服务 ...
- XAMARIN.ANDROID SIGNALR 实时消息接收发送示例
SignalR 是一个开发实时 Web 应用的 .NET 类库,使用 SignalR 可以很容易的构建基于 ASP.NET 的实时 Web 应用.SignalR 支持多种服务器和客户端,可以 Host ...
- APP并非一个人在战斗,还有API—Xamarin.Android回忆录
前言 一般来说,一个客户端APP并非独立存在的,很多时候需要与服务器交互.大体可分为两方面的数据,常规字符串数据和文件数据,因为这两种数据很可能传输方式不一样,比如字符串之类的数据,使用HTTP协议, ...
- Xamarin.Android通知详解
一.发送通知的机制 在日常的app应用中经常需要使用通知,因为服务.广播后台活动如果有事件需要通知用户,则需要通过通知栏显示,而在Xamarin.Android下的通知需要获取Notification ...
- [译]:Xamarin.Android开发入门——Hello,Android Multiscreen深入理解
原文链接:Hello, Android Multiscreen_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android Multiscreen深入理解. 本 ...
- Xamarin.Android之封装个简单的网络请求类
一.前言 回忆到上篇 <Xamarin.Android再体验之简单的登录Demo> 做登录时,用的是GET的请求,还用的是同步, 于是现在将其简单的改写,做了个简单的封装,包含基于Http ...
- Xamarin.Android之MvvmCross
欢迎大家加入以下开源社区 Xamarin-Cn:https://github.com/Xamarin-Cn Mvvmcross-Cn:https://github.com/Mvvmcross-Cn ...
- Xamarin.Android开发实践(十七)
Xamarin.Android之定位 一.前言 打开我们手中的应用,可以发现越来越多的应用使用了定位,从而使我们的生活更加方便,所以本章我们将学习如何在Xamarin中进行定位的开发. 二.准备工作 ...
随机推荐
- 看看Spring的源码(二)——bean实例化
首先来看一段代码,看过上一节的朋友肯定对这段代码并不陌生.这一段代码诠释了Spring加载bean的完整过程,包括读取配置文件,扫描包,加载类,实例化bean,注入bean属性依赖. public v ...
- JEECG 命名规范
举例讲解代码规范 例如:表名 :jeecg_sys_demo 第一部分:代码文件命名规则如下: 首先:表名采用驼峰写法转换为Java代码使用单词 jeecg_sys_demo => Jeecg ...
- 混沌分形之迭代函数系统(IFS)
IFS是分形的重要分支.它是分形图像处理中最富生命力而且最具有广阔应用前景的领域之一.这一工作最早可以追溯到Hutchinson于1981年对自相似集的研究.美国科学家M.F.Barnsley于198 ...
- C++/Php/Python 语言执行shell命令
编程中经常需要在程序中使用shell命令来简化程序,这里记录一下. 1. C++ 执行shell命令 #include <iostream> #include <string> ...
- 使用C++/libCurl/Jsoncpp读取arcgis wmts 服务(restful模式)
前言: 最近工作需要将arcgis的wmts服务接入我们的3DGis系统平台,要求用户只输入一个rest模式的wmts服务地址,系统即可自动获取并解析其元数据信息,生成wmts图层,并渲染显示.经过多 ...
- [leetcode]Combinations @ Python
原题地址:https://oj.leetcode.com/problems/combinations/ 题意:组合求解问题. 解题思路:这种求组合的问题,需要使用dfs来解决. 代码: class S ...
- 糟糕的css用法 1
现在网站追求越来越漂亮好看,越来越炫,所以css是必不可少的.可是我发现许多人使用css的方式是不对的,至少是不推荐的. 比如下面的css用法不对 (1)一个页面对应一个css文件 这种做法是我深恶痛 ...
- \r\n 如何转换成utf-8格式的,在jsp页面中正常显示换行
数据库中存的换行是\r\n,读取到UTF-8编码的JSP 页面上以后,没有换行 在jsp页面显示之前,要进行一下字符转换,将所有\r\n转换成<br>,如下: String result ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十四)定义一个avro schema使用comsumer发送avro字符流,producer接受avro字符流并解析
参考<在Kafka中使用Avro编码消息:Consumer篇>.<在Kafka中使用Avro编码消息:Producter篇> 在了解如何avro发送到kafka,再从kafka ...
- centos 新建swap区文件
一. 相当详细且流程完整,(推荐阅读) 在centos7上新建swap区 https://www.digitalocean.com/community/tutorials/how-to-add-swa ...