抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Service 是什么

Service 是一个App组件,可以在后台执行长时间运行的操作。它不提供用户界面。一旦启动,Service 可能会继续运行一段时间,即使在用户切换到另一个App之后也是如此。
此外,组件可以绑定到 Service 以与其交互,甚至执行进程间通信 (IPC)。 例如,Service 可以在后台处理网络事务、播放音乐、执行文件 I/O 或与ContentProvider交互。

Service 的类型

Service 有3种不同类型:

Foreground 前台服务执行一些用户可以注意到的操作。 前台服务必须显示通知。 即使用户没有与应用程序交互,前台服务也会继续运行。
当使用前台服务时,您必须显示通知,以便用户主动知道该服务正在运行。 除非服务停止或从前台删除,否则无法关闭此通知。

注意:WorkManager API 提供了一种灵活的任务调度方式,并且能够在需要时将这些Job作为前台服务运行。 在许多情况下,使用 WorkManager 比直接使用前台服务更可取。

Background 后台服务执行用户不直接注意到的操作。 例如,如果App使用服务来压缩其存储空间,那通常是后台服务。

Bound 当App组件通过调用 bindService() 绑定到服务时,服务被绑定。 绑定服务提供客户端-服务器接口,允许组件与服务交互、发送请求、接收结果,甚至通过进程间通信 (IPC) 跨进程执行此操作。
绑定服务仅在另一个App组件绑定到它时运行。 多个组件可以一次绑定到服务,但是当所有组件都解除绑定时,服务将被销毁。

基础

应该重写的最重要的回调方法:

onStartCommand() 当另一个组件请求启动服务时,系统通过调用 startService() 来调用此方法。 当这个方法执行时,服务就会启动并且可以无限期地在后台运行。 如果实现了这个,有责任在服务完成时通过调用 stopSelf() 或 stopService() 来停止服务。

onBind() 当另一个组件想要与服务绑定时,系统通过调用 bindService() 来调用此方法。 在此方法的实现中,必须通过返回一个 IBinder 来提供客户端用来与服务通信的接口。 必须始终实现此方法; 但是,如果不想允许绑定,则应返回 null。

onCreate() 系统在最初创建服务时(在调用 onStartCommand() 或 onBind() 之前)调用此方法来执行一次性设置过程。 如果服务已在运行,则不调用此方法。

onDestroy() 当服务不再使用并且正在被销毁时,系统会调用此方法。 应该实现它以清理任何资源,例如线程、注册的侦听器或接收器。 这是服务收到的最后一个调用。

如果组件通过调用 startService() 启动服务(这会导致调用 onStartCommand()),则服务会继续运行,直到它通过 stopSelf() 自行停止或另一个组件通过调用 stopService() 停止它。

如果组件调用 bindService() 来创建服务并且未调用 onStartCommand(),则服务仅在组件绑定到它时运行。 在服务与其所有客户端解除绑定后,系统将其销毁。

Android 系统仅在内存不足,并且必须为具有用户焦点的activity恢复系统资源时才停止服务。 如果服务绑定到具有用户焦点的activity,则它被杀死的可能性较小;
如果服务被声明在前台运行,它很少被杀死。 如果服务已启动并长时间运行,系统会随着时间的推移降低其在后台任务列表中的位置,并且该服务变得非常容易被杀死。
如果系统终止了服务,它会在资源可用时立即重新启动它,但这也取决于从 onStartCommand() 返回的值。

创建 started service

started service是另一个组件通过调用 startService() 启动的服务,这会导致调用服务的 onStartCommand() 方法。

当服务启动时,它的生命周期独立于启动它的组件。该服务可以无限期地在后台运行,即使启动它的组件已被销毁。因此,服务应该在其作业完成时通过调用 stopSelf() 自行停止,或者另一个组件可以通过调用 stopService() 来停止它。

注意:服务在与声明它的应用程序相同的进程中运行,并且默认情况下在该应用程序的主线程中运行。

注意 onStartCommand() 方法必须返回一个整数。 该整数描述了在系统终止服务的情况下系统应如何继续服务。 onStartCommand() 的返回值必须是以下常量之一:

START_NOT_STICKY 如果系统在 onStartCommand() 返回后终止服务,不会重新创建服务,除非有待交付的intent。

START_STICKY 如果系统在 onStartCommand() 返回后终止服务,则重新创建服务并调用 onStartCommand(),但不会重新传递最后一个intent。 相反,系统会以空intent调用 onStartCommand() ,除非有待启动的intent来启动服务。
在这种情况下,这些intent就会被传递。 这适用于不执行命令但无限期运行并等待作业的媒体播放器(或类似服务)。

START_REDELIVER_INTENT 如果系统在 onStartCommand() 返回后终止服务,请重新创建服务并使用传递给服务的最后一个intent调用 onStartCommand()。
依次传递任何未决intent。 这适用于正在积极执行应立即恢复的作业的服务,例如下载文件。

注意:如果应用需要创建前台服务,应用应该调用 startForegroundService()。 该方法创建了一个后台服务,但该方法向系统发出信号,该服务将把自己提升到前台。 创建服务后,服务必须在五秒内调用其 startForeground() 方法。

已启动的服务必须管理自己的生命周期。也就是说,系统不会停止或销毁服务,除非它必须恢复系统内存并且服务在 onStartCommand() 返回后继续运行。该服务必须通过调用 stopSelf() 来停止它自己,或者另一个组件可以通过调用 stopService() 来停止它。

一旦使用 stopSelf() 或 stopService() 请求停止,系统会尽快销毁服务。

如果服务同时处理对 onStartCommand() 的多个请求,则在处理完启动请求后不应停止服务,因为您可能收到了新的启动请求(在第一个请求结束时停止会终止第二个)。
为避免此问题,可以使用 stopSelf(int) 来确保您停止服务的请求始终基于最近的启动请求。也就是说,当调用 stopSelf(int) 时,传递的是停止请求对应的启动请求的 ID(传递给 onStartCommand() 的 startId)。
然后,如果服务在能够调用 stopSelf(int) 之前收到新的启动请求,则 ID 不匹配并且服务不会停止。

创建 bound service

要创建绑定服务,请实现 onBind() 回调方法以返回定义与服务通信的接口的 IBinder。然后其他应用程序组件可以调用 bindService() 来检索接口并开始调用服务上的方法。服务只为绑定到它的应用程序组件服务,所以当没有组件绑定到服务时,系统会销毁它。

要创建绑定服务,必须定义指定客户端如何与服务通信的接口。服务和客户端之间的接口必须是 IBinder 的实现,并且是服务必须从 onBind() 回调方法返回的内容。客户端收到 IBinder 后,就可以通过该接口开始与服务交互。

多个客户端可以同时绑定到服务。当客户端完成与服务的交互时,它调用 unbindService() 来解除绑定。当没有客户端绑定到该服务时,系统会销毁该服务。

前台服务

使用前台服务的应用必须请求 FOREGROUND_SERVICE 权限。

要从前台删除服务,请调用 stopForeground()。 此方法采用布尔值,指示是否也删除状态栏通知。 请注意,该服务将继续运行。

bound service

可以同时将多个客户端连接到一个服务。 但是,系统缓存了IBinder服务通信通道。 换句话说,只有在第一个客户端绑定时,系统才会调用服务的 onBind() 方法来生成 IBinder。 然后系统将相同的 IBinder 传递给绑定到相同服务的所有其他客户端,而无需再次调用 onBind()。

评论