概略
Service代表一个组件,当一个应用希望提供长期而不影响用户操作或者为其他应用提供功能时就可用到Service。每个Service类都需要在manifest.xml中用<service>进行声明。可以通过context.startService()和context.bindService()来启动。
和其他应用组件一样,Service运行在主线程中。这意味着,如果你的Service去做很CPU敏感的做如mp3播放或者网络操作,建议你用自已线程去完成。IntentService类是一个有自已线程的干自已活的标准实现。下面的讨论将涉及的内容:
1. 什么是Service?
2. Service的生命周期?
3. 权限
4. 进程周期
5. 本地服务实例
6.远程消息Service实例
1. 什么是Service?
很多关于Service的迷惑从下面几个不是进行理解:
(1) Service不是一个独立的进程。Serive对象并不意味着他运行在一个自已的进程中,除非特别的指定,他和应用运行在同一个进程,是应用的一部分。
(2) Service不是一个线程。不是脱离主线程独立工作。
因此,Service其实很简单,具有两个特征。
(1) Serive是一种基础设施,他告诉系统我想在后台干活,即使没有与用户的交互。这种方式可以通过context.startService()启动服务,这将告诉系统来拉起Service,开始工作直到服务或其他的服务显示的停止。
(2)Serivce是一种基础性设施,他将提供自已的功能给其他的应用。这种方式,可以通过context.bindService()启动服务,这可以保持一个很长时间的连接在服务与被服务的应用之间进行交互。
当一个Service组件真正被创建时,不管是因为上面的哪种理由,系统要做的是实例化一个组件,并调用其onCreate()和其他回调操作,这些都是主线程中完成。注意:因为Serivce自已是如此的简单,你能够做简单或复杂的操作,把他当做一个java对象来进行直接的方法调用,或用AIDL提供一个远程接口。
2. Service的生命周期?
有两个方法可以运行一个service。如果应用context.startService(),系统将重建Serice(create和onCreate),然后开始调用他的onStartCommand(Intent,int,int)方法。Serice将一直运行,直到调用context.stopService()或stopSelf()。多次调用context.startSerivce()不会嵌套,尽管会导致多次调用onStartCommand(),没必要提心启动多少次,而只调用一个停止。然而,service可以通过stopSelf(int)来确定,这服务没有被停掉直到开始的Intent被处理。
为了启动服务,这里有有两运行时的模式,依赖于onStartComand()的返回值:START_STICKY被用于那些显示开始和停止的服务,而START_NOT_STICKY或者START_REDELIVER_INTENT被用于服务,他仅仅要求运行当处理任何命令。详见具体文档。
客户端可以通过context.bindService()来获得服务。如果被绑定的服务没有运行时,和上面创建的过程相似(onCreate),但不调用onStartCommand()。客户端将收到IBinder对象。允许客户端调用Service提供的服务。这个服务从连接开始将一直运行,(取决于行客户端是否持有IBinder的引用)。一般IBinder一个用aidl写的复杂接口。一个服务能够通过Start和Bind进行启动,在一种情况下,系统将保持service一直处于运行状态只有被启动或者Bind过,通过context.BIND_AUTO_CREATE标记。只要不上面这种情形,Service的onDestroy()方法被调用,Serivce将被终结。所有清理工作,比始停止线程,都应该在onDestroy()中进行。
3. 权限
全局的访问一个serivce能够通过在menifest中声明<service>来实现,其他的应用需要声明<uses-permission>在他自已的menifest中,以使其能够开始停止和绑定服务。比如Gingerbread中,当使用context.startService(Intent),你将可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION和Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这将同意service临时访问特定的URI。此权限将直到service调用stopSelf(int)。
4. 进程周期
系统将尝试保证一个服务从开始启动一直运行,但当低内存需要杀掉存在的进程时,一个带服务进程的优先级将高一些:
a. 如果service正在执行onCreate(),onStartCommand()或onDestroy()方法时,这个宿主进程是一个前台进程,保证代码执行完成而不会被kill掉。
b. 如要服务已经启动,如果serivce的宿主进程没有其他前台进程的优先级高,但比任何不可见进程重要。因为仅一些进程可见,这意味着那些Service将不会被kill掉,除非系统内存处理极低情况下。
c. 如果一个客户端绑定一个serivce,因此这个服务的宿主进程将不可能不重要。因此,如果一个客户端是可见的,那么他的服务也是可见的。
d. 通过startForeground(int, Notification)API来启动服务,来将服务拉到前台状态。这种情况下,也不会被kill掉。
所以你的serivce大部分情况下,处于运行状态。除非内存非常吃紧的情况下。如果这种情况发生了,系统将过会重启服务。
本地serivce实例: