android Service介绍
一、简介
android中service(服务)运行于后台,没有界面。和其他组件一样,service也运行在主线程中,因此不能用它来做耗时的请求或者动作。可以在服务中开启线程,在线程中做耗时操作。可以启动一个服务service来播放音乐,或者记录地理信息位置的改变,或者启动一个服务来运行并一直监听某种动作。
二、Service的种类
服务一般分为两种:
1、本地服务,Local Service用于应用程序内部。
在Service可以调用Context.startService()启动,调用Context.stopService()结束。在内部可以调用Service.stopSelf() 或Service.stopSelfResult()来停止。无论调用了多少次startService(),都只需调用一次stopService()来停止。调用startForeground()方法可以将服务运行于前台并在通知栏展示。
2、远程服务,Remote Service用于android系统内部的应用程序之间。
可以定义接口并把接口暴露出来,以便其他应用进行操作。客户端建立到服务对象的连接,并通过那个连接来调用服务。调用Context.bindService()建立连接并启动,调用Context.unbindService()关闭连接。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。提供给可被其他应用复用,比如定义一个天气预报服务,提供与其他应用调用即可。
三、Service的生命周期
1、被启动的服务的生命周期:
如果一个Service被某个Activity调用Context.startService方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此停止服务只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
2、被绑定的服务的生命周期:
如果一个Service被某个Activity调用Context.bindService方法绑定启动,不管调用bindService调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService断开连接或者之前调用bindService的Context不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
3、被启动又被绑定的服务的生命周期:
如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用stopService或Service的stopSelf来停止服务。
4、当服务被停止时清除服务:
当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。
特别注意:
1、在调用bindService绑定到Service的时候,你就应当保证在某处调用unbindService解除绑定(尽管Activity被finish的时候绑定会自动解除,并且Service会自动停止)。
2、使用startService启动服务之后,一定要使用stopService停止服务,不管你是否使用bindService。
3、同时使用startService与bindService要注意到,Service的终止,需要unbindService与stopService同时调用,才能终止Service,不管startService与bindService的调用顺序,如果先调用unbindService此时服务不会自动终止,再调用stopService之后服务才会停止,如果先调用stopService此时服务也不会终止,而再调用unbindService或者之前调用bindService 的Context不存在了(如Activity 被 finish 的时候)之后服务才会自动停止。
4、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context不存在了),对应服务的生命周期与上述相同。
5、在sdk2.0及其以后的版本中,对应的onStart已经被否决变为了onStartCommand,不过之前的onStart仍然有效。这意味着,如果你开发的应用程序用的sdk为2.0及其以后的版本,那么你应当使用onStartCommand而不是onStart。
Service的生命周期图如下:
通过startService启动的服务:
context.startService() ->onCreate()- >onStartCommand()->Service running—
调用context.stopService() ->onDestroy()
通过bindService启动的服务:
context.bindService()->onCreate()->onBind()->Service running—
调用>onUnbind() -> onDestroy()
四、本地服务(Locale Service)的绑定
实现步骤:
1、在Service中实现抽象方法onBind(),并返回一个实现IBinder接口的对象。
2、在Activity中通过ServiceConnection接口来获取连接建立与连接断开的回调。
bindService()方法绑定服务,有三个参数,第一个是用于区分Service的Intent,与startService中的Intent 一致,第二个是实现了ServiceConnection接口的对象,第三个是flag标志位。有两个flag,Context.BIND_DEBUG_UNBIND与Context.BIND_AUTO_CREATE,前者用于调试,后者默认使用。
unbindService()方法解除绑定,参数则为之前创建的ServiceConnection接口对象。另外,多次调unbindService()来释放相同的连接会抛出异常,需要添加判断是否unbindService 已经被调用过。
五、远程服务(Remote Service)的绑定
Local Service,即Service和Client在同一进程内(即同一application内),Service的生命周期服从进程的生命周期。在实际应用中,有时希望Service作为后台服务,不仅被同一进程内的activity使用,也可被其他进程所使用。
通常每个应用程序都在它自己的进程内运行,但有时需要在进程之间传递对象(IPC通信)。在android平台中,一个进程通常不能访问其它进程中的内存区域,需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问,android为我们提供了AIDL工具来做这件事。
Android提供AIDL(Android Interface Definition Language)工具帮助IPC之间接口的建立,AIDL是一种IDL语言(接口定义语言),可以生成一段代码,使android设备上运行的两个进程使用内部通信进程进行交互。如果需要在一个进程中(例如在一个Activity中)访问另一个进程中(例如一个Service)某个对象的方法,就可以使用AIDL来生成这样的代码来伪装传递各种参数。
通过下面的步骤实现client和service之间的通信:
1)定义AIDL接口,例如IServiceInterface.aidl
2)Client连接Service,连接到IServiceInterface暴露给Client的Stub,获得stub对象;即Service通过接口中的Stub向client提供服务,在IServiceInterface中对抽象IServiceInterface.Stub具体实现。
3)Client和Service连接后,Client可像使用本地方法那样直接调用IServiceInterface.Stub里面的方法。
同一App应用的activity与service也可以在不同进程间,可以在Service配置中设置android:process=":remote"。
在不同的进程之间传递数据,Android对这类数据的格式支持非常有限,基本上只能传递Java的基本数据类型、字符串、List或Map等。如果想传递一个自定义的类必须要让这个类去实现Parcelable接口,并且给这个类也定义一个同名的AIDL文件。
SDK5.0后调用远程服务需要指定包名:intent.setPackage("PackageName");
注意:
Service.onBind()如果返回null,则调用bindService会启动Service,但不会连接上Service,因此ServiceConnection.onServiceConnected不会被调用,但仍然需要使用 unbindService函数断开它,这样Service才会停止。
六、Service与Thread的区别
1、Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
2、Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的Service是运行在主进程的main线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的main线程上运行的。如果是Remote Service,那么对应的Service则是运行在独立进程的main线程上。
因此不要把Service理解成线程,两者没有关联。
拥有service的进程具有较高的优先级
根据官方文档,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。
1、如果service正在调用onCreate,onStartCommand或者onDestory方法,那么用于当前service的进程则变为前台进程以避免被killed。
2、如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.
3、如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。
4、如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。
如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。
控制service运行的主要方式有两种,主要是根据onStartCommand方法返回的数值。START_STICKY、START_NOT_STICKY or START_REDELIVER_INTENT。
1、START_STICKY
在运行onStartCommand后service进程被kill后,那将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建 service后将保证调用onStartCommand。如果没有传递任何开始命令给service,那将获取到null的intent。
2、START_NOT_STICKY
在运行onStartCommand后service进程被kill后,并且没有新的intent传递给它。Service将移出开始状态,并且直到新的明显的方法(startService)调用才重新创建。因为如果没有传递任何未决定的intent那么service是不会启动,也就是期间onStartCommand不会接收到任何null的intent。
3、START_REDELIVER_INTENT
在运行onStartCommand后service进程被kill后,系统将会再次启动service,并传入最后一个intent给onStartCommand。直到调用stopSelf(int)才停止传递intent。如果在被kill后还有未处理好的intent,那被kill后服务还是会自动启动。因此onStartCommand不会接收到任何null的intent。
Service的种类
按运行地点分类:
类别 |
区别 |
优点 |
缺点 |
应用 |
本地服务(Local) |
该服务依附在主进程上, |
服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多。 |
主进程被Kill后,服务便会终止。 |
非常常见的应用如:HTC的音乐播放服务,天天动听音乐播放服务。 |
远程服务(Remote) |
该服务是独立的进程, |
服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。 |
该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。 |
一些提供系统服务的Service,这种Service是常驻的。 |
其实remote服务还是很少见的,并且一般都是系统服务。
按运行类型分类:
类别 |
区别 |
应用 |
前台服务 |
会在通知一栏显示 ONGOING 的 Notification, |
当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务。 |
后台服务 |
默认的服务即为后台服务,即不会在通知一栏显示 ONGOING 的 Notification。 |
当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新,日期同步,邮件同步等。 |
有同学可能会问,后台服务我们可以自己创建 ONGOING 的 Notification 这样就成为前台服务吗?答案是否定的,前台服务是在做了上述工作之后需要调用 startForeground ( android 2.0 及其以后版本 )或 setForeground (android 2.0 以前的版本)使服务成为 前台服务。这样做的好处在于,当服务被外部强制终止掉的时候,ONGOING 的 Notification 任然会移除掉。
按使用方式分类:
类别 |
区别 |
startService 启动的服务 |
主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService |
bindService 启动的服务 |
该方法启动的服务要进行通信。停止服务使用unbindService |
startService 同时也 bindService 启动的服务 |
停止服务应同时使用stepService与unbindService |
在 AndroidManifest.xml 里 Service 元素的常见选项
android:name ------------- 服务类名
android:label -------------- 服务的名字,如果此项不设置,那么默认显示的服务名则为类名
android:icon -------------- 服务的图标
android:permission ------- 申明此服务的权限,这意味着只有提供了该权限的应用才能控制或连接此服务
android:process ---------- 表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字
android:enabled ---------- 如果此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false
android:exported --------- 表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false
android Service介绍的更多相关文章
- Android service介绍和启动方式
1.Android service的作用: service通常是用来处理一些耗时操作,或后台执行不提供用户交互界面的操作,例如:下载.播放音乐. 2.Android service的生命周期: ser ...
- Android——Service介绍与例子
官方定义:Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件.其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行.另外,一个组件 ...
- Android Service总结02 service介绍
Android Service总结02 service介绍 版本 版本说明 发布时间 发布人 V1.0 介绍了Service的种类,常用API,生命周期等内容. 2013-03-16 Skywang ...
- Android Service完全解析,关于服务你所需知道的一切(下)
转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...
- Android Service完全解析,关于服务你所需知道的一切(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952435 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的A ...
- 【转】Android Service完全解析,关于服务你所需知道的一切(下) ---- 不错
原文网址:http://blog.csdn.net/guolin_blog/article/details/9797169 转载请注册出处:http://blog.csdn.net/guolin_bl ...
- Android Service(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952435 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的A ...
- Android Service(下)
转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...
- Service介绍(MediaPlayer应用)
一.Service介绍 Service类似于Windows中的服务,没有界面,只是在后台运行:而服务不能自己运行,而是需要调用Context.startService(Intent intent);或 ...
随机推荐
- [DeviceOne开发]-手势动画示例分享
一.简介 这是iOS下的效果,android下完全一致.通过do_GestureView组件和do_Animation组件,deviceone能很容易实现复杂的跨平台纯原生动画效果,这个示例就是通过手 ...
- Fedora 22中的DNF软件包管理工具
Introduction DNF is the The Fedora Project package manager that is able to query for information abo ...
- Kinect开发文章目录
整理了一下去年为止到现在写的和翻译的Kinect的相关文章,方便大家查看.另外,最近京东上微软在搞活动, 微软 Kinect for Windows 京东十周年专供礼包 ,如果您想从事Kinect开发 ...
- 自定义view(一)
最近在学习自定义view 一遍看一别学顺便记录一下 1.View的测量-------->onMeasure() 首先,当我们要画一个图形的时候,必须知道三个数据:位置,长度,宽度 才能确定 ...
- iOS-----程序异常处理----- 断言NSAssert()和NSParameterAssert区别和用处
NSAssert和assert是断言,主要的差别是assert在断言失败的时候只是简单的终止程序,而NSAssert会报告出错误信息并且打印出来.所以尽管的使用NSAssert,可以不去使用asser ...
- 4.2w起步的软件公司创业历程
调查说,中国民营企业的生命期平均是2.8年,如今我的企业已走过近四年,而这一年却是我的迷茫期,不知道何去何从,现在写下 来与大家一起分享一下,写得较为凌乱,大家将就着看一下吧:) 先交待一下自己,我来 ...
- HTML5权威指南--标签新变化,文件API,拖放API(简要学习笔记一)
1.标签元素更加语义化 2.内容类型仍然为“text/html” 扩展符仍然为html或者htm. <1>DOCTYPE 声明<!DOCTYPE html>就可 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(48)-工作流设计-起草新申请
系列目录 创建新表单之后,我们就可以起草申请了,申请按照严格的表单步骤和分支执行. 起草的同时,我们分解流转的规则中的审批人并保存,具体流程如下 接下来创建DrafContoller控制器,此控制器只 ...
- Web缓存杂谈
一.概述 缓存通俗点,就是将已经得到的‘东东’存放在一个相对于自己而言,尽可能近的地方,以便下次需要时,不会再二笔地跑到起始点(很远的地方)去获取,而是就近解决,从而缩短时间和节约金钱(坐车要钱嘛). ...
- React学习笔记。
有段时间没写博客了,最近这段时间有点说不出的苦,虽然说年轻的时候该多出去经历些事,但每次找工作东跑西跑,坐公交坐地铁浪费了我太多时间,我感觉到这是一种浪费,对生命的浪费.所以很想尽快找到一份工作,去努 ...