Service是一个应用组件,它可以在后台执行耗时的操作,没有对用户提供一个界面。
Service分为两类:
1、Started
应用组件通过调用startService()方法启动Service。一旦service启动,它将在后台无限期运行,即使在启动它的组件被销毁的情况下。通常情况下,一个Started Service执行一个单一的操作且不返回任何结果给启动它的组件。
2、Bound
应用组件通过调用bindService()方法绑定到Service上时,这个Service是Bound Service。Bound Service提供一个客户端(client)接口,允许用户组件与之交互。Bound Service与绑定它的组件的生命周期一样长。
无论应用请求的是哪种服务,任何组件都可以使用该服务。同样的,任何组件都可以通过activity使用intent启动一个service。然而,你可以在配置文件manifest中将服务声明为私有的,阻止其他应用程序访问。
注意:Service运行在他所在的主进程的主线程中,Service并没有启动一个新的线程(除非你特别指定)。这意味着如果Service执行一些CPU比较耗时的操作或者异步的操作,你需要在Service中创建一个新的线程来执行这类操作。
基础知识
要创建一个服务,必须要创建一个Service的子类。在这个子类的实现中必须重载一些比较重要的回调函数。这些回调函数将在Service的生命周期的关键部分处理交互的接口一些重要的事情,并为组件提供绑定Service的机制。下面列出一些比较重要的回调函数:
当其他组件通过调用startService()方法请求启动一个Service时,系统会调用这个方法来启动这个Service。一旦这个方法被执行,Service立即启动并在后台无限期运行。如果你实现该方法,你必须在任务完成后,调用
方法停止这个Service。(如果你仅仅想提供绑定功能,则不需要实现这个方法)stopSelf()
或者 stopService()
2、onBind()
当其他组件通过调用bindService()
方法请求绑定一个Service时,系统会调用这个方法。在这个方法的实现中,你必须要提供一个客户端与Service交互的接口,这个接口返回一个IBinder
对象。你必须实现这个方法,当你不希望其他组件绑定这个服务时,这个方法实现返回null。
当这个Service第一次创建时,系统会调用这个方法用来执行一次性设置程序。它发生在调用onStartCommand()
方法或者onBind()方法
前。如果Service已经运行,这个方法不会被调用。
当这个Service不再使用被销毁时系统会调用这个方法。必须要实现这个方法来清除资源。
当一个组件调用startService()方法启动一个Service
时,这个Service只有在它自己调用stopSelf()
或者其他组件调用stopService()
才能停止这个Service
。
当一个组件调用bindService()方法创建一个Service,一旦这个Service未被客户端绑定时,系统会自动销毁这个Service。
创建一个Started Service
一个组件例如activity可以通过调用startService()方法启动一个Started Service,该方法需要一个Intent类对象参数用来指定Service和向Service传递一些数据。Service将在onStartCommand()
方法中接收这个Intent对象。
注意:默认情况下,Service运行在声明它的哪个application所在的进程的main线程中。
通常有两种可用于继承的类来创建Started Service:
1、Service
它是Service的一个子类,该子类使用work thread来请求。当你不要求同时处理多个请求时这是最佳的选择。我们需要做的是实现onHandleIntent()
方法。这个方法接收启动Service请求的intent。
IntentService
做了如下工作:
a.创建一个处理intents的默认work线程
b.创建一个work队列,每次传递一个intent给onHandleIntent()
c.当所有请求处理完毕时,停止service,无须调用stopSelf()方法
d.提供
的默认实现,返回nullonBind()
e.提供onStartCommand()
的默认实现,将intent发送到work队列
我们需要做的是提供一个简单的构造器和onHandleIntent()方法的实现。
停止一个started service
一个started service必须自己管理自己的生命周期。Service可以自己调用stopSelf()方法,或者由其他组件调用stopService()方法来停止Service。
创建一个Bound Service
Bound Service是一个允许应用程序组件通过调用bindService()
方法与器绑定的Service,目的是为了建立一个长时间的连接。
为了创建一个Bound Service,必须实现onBind()
回调函数,返回一个Ibinder对象。这个Ibinder对象是与Service交互的接口。其他组件可以通过调用bindService()
得到这个接口,并调用Service中的方法。Bound Service仅对和它绑定的组件起作用,因此当没有组件和Bound Service绑定时,系统会自动销毁该服务。(前提是没有组件通过onStartCommand()
方法启动这个Service)
创建一个Bound Service的第一步是定义客户端与Service之间交互的接口。这个接口必须是IBinder
类的一个实现,是通过onBind()
回调方法返回的。一旦客户端接收到这个
类对象就可以与Service进行交互。IBinder
当一个客户端和Service交互完毕,就可以调用
unbindService()
方法解除绑定,一旦没有客户端绑定Service,系统就会销毁Service。
Bound Service
public abstract boolean bindService (Intent service, ServiceConnection conn, int flags)
客户端通过调用bindService()
方法来绑定Service,这个方法需要实现一个ServiceConnection类对象,这个类对象用来监视连接过程。当Android系统建立客户端与Service之间的连接的时候,系统调用ServiceConnection
中的onServiceConnected()
方法,系统会将IBinder
对象传递给这个方法。
可以同时有多个客户端绑定到Service上,但是系统只会在第一个客户端绑定请求时调用
onBind()
方法并返回一个
对象。当有后续的绑定请求时,系统不再调用IBinder
,直接将以前生成的onBind()
方法
传递给客户端。
对象IBinder
实现
对象接口IBinder
有3种方法可以定义这个接口:
1、继承
类IBinder
当你的Service是对你自己的应用程序是私有的,并且和客户端在同一个进程中的时候(这是一种常见的现象),你可以通过继承
类来创建接口,在Service的IBinder
方法返回onBind()
类实例。客户端接收这个IBinder
类实例,可以访问IBinder
类实例和Service中公有方法。IBinder
这是我们首选的实现技术,唯一不使用这种方法实现接口的原因是你的Service要被其他application使用或者这个Service使用一个单独的进程。
如果你想让你接口在不同的进程间工作,你可以为Service创建一个带有Messenger
的接口。在这种情况下,服务将定义一个Handler
来处理消息。Handler
是Messenger
的基础,它可以与客户端共享一个
类对象,客户端可以使用IBinder
Message
对象发送命令至Service。除此之外,客户端也可以自己定义一个Messenger
对象,这样Service就可以回送消息至客户端。
这是最简单的执行进程间通信(IPC)的方法,因为Messenger
将所有请求排队送入到一个单独的线程中,因此你不需要将Service设计成线程安全的。
3、Using AIDL
只有Activity、Service和Content Provider绑能定一个Servicer。
ServiceConnection
类的实现有两个抽象回调函数:
onServiceConnected()
和onServiceDisconnected()
。
系统调用
方法传递onServiceConnected()
类对象。IBinder
当客户端与Service之间的连接异常消失时,系统会调用
onServiceDisconnected()
方法,譬如Service崩溃或者被杀死的时候。当客户端调用unbindService()
方法时,系统不调用此方法。