一个Service也是一种应用程序组件,它运行在后台以提供某种服务,通常不具有可见的用户界面。其它的应用程序组件可以启动一个Service,即使在用户切换到另外一个应用程序后,这个Service还是一直会在后台运行。此外,一个应用程序也可以绑定到一个Service然后使用进程间通信(IPC)方式与Service之间发生交互。例如一个Service可以处理网络事物,播放音乐,读写文件或者读写ContentProvider,所以这些都在后台运行。
一个Service可以以以下两种形式存在:
· Started(启动) 在一个应用程序以startService() 来启动一个Service时,这个Service将处于“Started”状态。一旦启动,这个Service可以在后台一直运行下去,即使启动它的应用程序已推出。通常,一个处于“started”状态的Service完成某个功能而不会给启动它的应用程序组件返回结果。比如,这个服务(Service)可能是上载或是下载一个文件,当任务完成后,服务自行退出。
· Bound (绑定) 当一个应用程序组件以bindService() 绑定一个Service时,这个Service处于“Bound”状态。处于“Bound”状态的Service提供了一个客户/服务(C/S)调用接口支持其它应用程序组件和它交互,比如发生请求,返回结果,或者使用IPC完成跨进程间通信。一个处于“Bound”的Service只能和与其绑定的应用程序一起运行。多个应用程序组件可以绑定到同一个Service。当所有绑定的应用程序组件都退出绑定后,被“绑定”的Service将被销毁。
对于一个Service来说,它可以是“Started”,“Bound”或者同时处于两种状态。其它任一应用程序组件(比如一个Activity)都可以使用这个Service,即使其它应用程序组件是在不同的应用程序中。当然你可以把Service定义为私有的,这样其它应用程序就无法使用你定义的Service。
要注意的是,一个Service运行在其宿主进程的主线程中--服务不会自己创建新的线程也不运行在独立的进程中(除非你特别指明)。这意味着,如果你的Service需要完成一些很耗CPU资源的操作(比如播放MP3,或者使用网络),你应该在Service中创建新的线程来完成这些工作,从而降低出现程序无响应(ANR)的风险。
Service基础
要创建一个Service,你必须从Service或是其某个子类派生子类。在你的Service子类实现中,你需要重载一些方法以支持Service重要的几个生命周期函数和支持其它应用组件绑定的方法。下面给出几个需要重载的重要方法:
· onStartCommand() Android系统在有其它应用程序组件使用startService()请求启动Service时调用。一旦这个方法被调用,Service处于“Started”状态并可以一直运行下去。如果你实现了这个方法,你需要在Service任务完成时调用stopSelf()或是stopService()来终止服务。如果你只支持“绑定”模式的服务,你可以不实现这个方法。
· onBind() Android系统中有其他应用程序组件使用bindService()来绑定你的服务时调用。在你实现这个方法时,你需要提供一个IBinder接口以支持客户端和服务之间通信。你必须实现这个方法,如果你不打算支持“绑定”,返回Null即可。
· onCreate() Android系统中创建Service实例时调用,一般在这里初始化一些只需单次设置的过程(在onStartCommand和onBind()之前调用),如果你的Service已在运行状态,这个方法不会被调用。
· onDestroy() Android系统中Service不再需要,需要销毁前调用。在你的实现中你需要释放一些诸如线程,注册过的listener,receiver等,这是Service被调用的最后一个方法。
如果一个Service是由startService()启动的(这时 onStartCommand()将被调用),这个Service将一直运行直到调用stopSelf()或其它应用部件调用stopService()为止。
如果一个部件调用bindService()创建一个Service(此时onStartCommand()不会调用),这个Service运行的时间和绑定它的组件一样长。一旦其他组件解除绑定,系统将销毁这个Service。
Android系统只会在系统内存过低且不得不为当前活动的Activity恢复系统资源时才可能强制终止某个Service。如果这个Service绑定到一个活动的Activity,基本上不会被强制清除。如果一个Service被申明成“后台运行”,就几乎没有被销毁的可能。否则的话,如果Service启动后并长期运行,系统将随着时间的增加降低其在后台任务中的优先级,其被杀死的可能性越大。如过你的Service是做为“Started”状态运行,你必须设计后如果在系统重启服务时优雅退出。如果系统杀死你的服务,系统将在系统资源恢复正常时重启你的服务(当然这也取决于onStartCommand()的返回值)。
在Manifest中申明Service
和Activity一样,你必须在Manifest文件中申明应用中使用到的Service。为了声明一个Service,你需要定义<application>的子元素<service>,比如:
[html]
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
<service>还包括一些其它属性,android:name是唯一一个必须定义的属性,它定义了Service的类名。
和Activity一样,你可以为Service定义Intent Filter以支持其它部件隐式调用该服务。如果你只打算在你自己的应用中使用某个Service,那么就不要定义任何Intent Filter。在这种情况下,你必须明确指明Service的类名来启动这个Service。此外,你可以通过设置android:exported属性为false来明确说明该Service为私有,即使你为Service定义了Intent Filter ,其它应用也无法使用你的Service。
创建一个“Started”的Service
当其它应用程序组件使用startService()来启动Service后,这个Service就成为“Started”的Service。这时Service的onStartCommand () 回调函数将会被调用。
当一个Service以startService()启动后,处于“Started”状态,其生命周期独立于启动这个Service的其它应用程序组件,并且可以在后台无限期运行,即使启动它的其它应用程序组件已经退出。在这种情况下,Service可以调用stopSelf()或者其它程序部分调用stopService()来结束这个Service。
一个应用程序组件比如一个Activity可以通过传入Intent使用startService()来启动一个Service,这个Intent指明需要的服务并包含了Service需要的数据。Service在onStartCommand回调函数中可以访问这个Intent。
要注意的是,Service缺省和申明它的应用程序使用同一个进程并且运行在主线程中,因此如果你的Service比较耗时的话,那么这个Service会影响到应用的用户响应性能。为避免这种现象,你应用在Service中创建新线程。
你可以使用下面两个基类来创建一个“Started”的Service。
· Service 这是所有Service的基类,当你派生这个类时,使用新创建的线程来完成Service需要完成的工作非常重要,这是因为Service缺省也会使用你的应用程序的主线程,这可能会影响你应用程序的响应性能。
· IntentService 为Service的一个子类,它会使用一个工作线程来处理所有的请求,每次处理一个请求。这在你无需实现并行处理多个请求时是最好的选择。你只需重载onHandleIntent()方法,这个方法接受每个请求,从而你可以在后易做图成所需任务。
派生IntentService类
因为大部分“Started”的Service不需要并行处理多个请求,这时最好的选择是派生自IntentService。
类IntentService可以完成以下工作:
· 创建一个工作线程来处理所有发送到onStartCommand()的请求(Intent),从而和应用的主线程分开。
· &nbs
补充:移动开发 , Android ,