Service
Service
Class Overview 提要
Service Lifecycle 服务生命周期
Permissions 权限
Process Lifecycle 进程生命周期
Summary 总结
Class Overview 提要
服务(Service)是一个在后台运行的组件, 它一直保持运行, 并且不和用户进行交互. 每个服务类必须在它所在的包的AndroidManifest.xml中有一个声明. Service使用Context.startService() 和 ontext.bindService()启动.
和其他应用程序对象一样, 服务在主线程中运行. 这意味着如果你的服务想做任何CPU密集型或者阻塞性的操作, 那么最好是创建一个线程来做.
Service 类是应用程序的生命周期中的重要组成部分.
Service Lifecycle 服务生命周期
系统启动服务有两个原因. 如果有人调用Context.startService(), 那么启动会获取该服务(如果需要的话使用onCreate()来创建它)然后调用它的onStartCommand(Intent, int, int)方法, 传入客户提供的参数. 这时候服务会一直运行直到Context.stopService()或者stopSelf()被调用. 注意多个Context.startService()调用不会嵌套(虽然它们会导致多个onStartCommand()调用), 所以无论服务被启动了多少次, 一旦调用Context.stopService()或者stopSelf(), 则服务就会停止. 服务可以使用stopSelf(int)方法来保证启动的intent被处理后才会被停止.
对于启动了的服务, 根据onStartCommand()返回值的不同, 有两种额外的操作模式.
START_STICKY是显式启动和停止的服务使用的, 而START_NOT_STICKY 或者START_REDELIVER_INTENT是只在处理命令时才运行的服务使用的.
START_NOT_STICKY 如果服务进程在它启动后(从onStartCommand()返回后)被kill掉, 并且没有新启动的intent传给他, 那么将服务移出启动状态并且不重新生成, 直到再次显式调用Context.startService().
START_REDELIVER_INTENT 如果服务进程在它启动后(从onStartCommand()返回后)被kill掉, 那么它将会被重启, 并且最后传给它的intent会被重新传给它, 通过onStartCommand(Intent, int, int).
START_STICKY 如果服务进程在它启动后(从onStartCommand()返回后)被kill掉, 那么让他呆在启动状态但不取传给它的intent.
客户也可以使用Context.bindService()来取得和服务的永久性链接. 如果服务没有启动, 那么这将创建它(调用onCreate()),
但不会调用onStartCommand(). 客户将获取IBinder对象, 这些对象由服务的onBind(Intent)方法返回, 以便客户能够向服务发出调用. 只要链接建立, 服务就会一直运行(不管客户是否保留服务的IBinder的引用). 通常IBinder是使用aidl写成的一个复杂接口.
一个服务同时可以被启动并连接. 在这样的情形下, 系统将让该服务保持运行,只要它是启动状态,或者有Context.BIND_AUTO_CREATE标志的连接. 当这两个条件都不满足时, 该服务的onDestroy()方法被调用, 服务被终止. 所有的清理工作(停止线程, 注销接收器)应该在onDestroy()中完成.
Permissions 权限
如果一个服务在manifest中的中声明一个服务的强制全局访问, 那么其它的应用程序必须在对应的元素中做相应的声明, 以便启动,停止或者绑定该服务.
此外, 一个服务可以使用权限来保护一个IPC调用. 使用 checkCallingPermission(String) 方法.
Process Lifecycle 进程生命周期
android系统会试图保持持有服务的进程运行, 只要该服务被启动或者有客户连接它. 当内存不足时, 持有服务的进程将有较高的优先级:
如果服务正在它的 onCreate(), onStartCommand()或者onDestroy()中运行, 那么持有服务的进程将变为前台进程.
如果服务已经被启动了, 那么持有它的进程被认为比当前对用户可见的进程次要, 但比其它不可见的进程重要.
如果有客户连接到服务, 那么该服务的进程的重要性不低于重要性最高的客户进程.
一个已启动的服务可以诗意哦能够startForeground(int, Notification) API来将服务放在前台状态, 系统认为它是用户可见的, 因此在内存低的时候不会被kill.
注意这意味着大部分服务在运行的时候, 它有可能被系统Kill掉. 这样, 系统之后会重启该服务. 如果你实现onStartCommand()来安排异步工作或者在另一个线程中工作, 那么你可能需要使用START_FLAG_REDELIVERY来让系统重新发送一个intent这样如果你的服务在处理它的时候被Kill掉, Intent不会丢失.
Summary 总结
公有方法
final ApplicationgetApplication()
返回持有该服务的应用程序.
abstract IBinderonBind(Intent intent)
返回该服务的通信通道.
void onCreate()
该服务第一次被创建时调用.
void onDestroy()
当服务不再使用并即将被清除时调用.
void onRebind(Intent intent)
在onUbind()通知的断开连接的客户再次连接到服务时调用.
int onStartCommand(Intent intent, int flags, int startId)
每次一个客户显式启动该服务 (使用startService(Intent))时调用.
boolean onUnbind(Intent intent)
当所有客户都和服务的某个接口断开连接时调用.
final void startForeground(int id, Notification notification)
让服务运行在前台, 并给用户提示.
final void stopForeground(boolean removeNotification)
将服务从前台移除, 在需要内存时可以被Kill.
final void stopSelf()
如果它被启动了, 停止该服务.
final boolean stopSelfResult(int startId)
如果最近一次调用它的是startId, 那么停止服务.