google开发者文档是最好的老师,网络上文章大多是个人解读,因人而异。 google开发者文档--服务概览
Service介绍
Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件,从服务类型上看有以下三种:
- 前台服务:前台服务执行一些用户能注意到的操作,前台服务必须显示,即使用户停止与应用的交互,前台服务仍会继续运行。(例如 网易云音乐播放音乐,迅雷下载,即使应用处于后台,前台仍会有长时间驻留通知)
- 后台服务:后台服务执行用户不会直接注意到的操作。(例如后台压缩文件)
- 需要注意的是android O开始对后台服务进行限制,app处于
空闲期会停止正在运行的后台服务,所以google推荐使用JobScheduler可以处理大多数的后台任务,如果项目使用了jetpack大礼包,可以使用 google开发者文档--后台处理指南 介绍根据任务类型分别使用协程、WorkManager、AlarmManager来处理。
- 需要注意的是android O开始对后台服务进行限制,app处于
- 绑定服务:当应用组件通过调用
bindService()绑定到服务时,服务即处于绑定状态。- 绑定服务会提供客户端-服务器接口,以便组件与服务进行交互、发送请求、接收结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。
- 仅当与另一个应用组件绑定时,绑定服务才会运行。
- 多个组件可同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
从启动的方式上看有2种方式
-
start方式
- 该服务在其他组件调用
startService()时创建,然后无限期运行,且必须通过调用stopSelf()来自行停止运行。此外,其他组件也可通过调用stopService()来停止此服务。服务停止后,系统会将其销毁。
- 该服务在其他组件调用
-
bind方式
- 该服务在其他组件(客户端)调用
bindService()时创建。然后,客户端通过IBinder接口与服务进行通信。客户端可通过调用unbindService()关闭连接。多个客户端可以绑定到相同服务,而且当所有绑定全部取消后,系统即会销毁该服务。(服务不必自行停止运行。) 需要注意的是 这两种方式并不互斥即可以start方式并且bind方式启动一个service(例如 播放音乐服务 即让其服务无限期运行并同时提供绑定很有用处,应用处于后台时,这是一个前台服务可以长久运行,应用来到前台时也要和控制界面进行绑定,以此来控制播放器,此类情况下,在所有客户端取消绑定之前,stopService()或stopSelf()实际不会停止服务)
- 该服务在其他组件(客户端)调用
俩种方式的生命周期如下图所示
对于多次调用解惑
-
startService
- Service只能被创建一次,即onCreate()方法只会被调用一次。
- 每次调用startService(),onStartCommand()方法都会被调用(onStart方法在API 5时被废弃)。
-
bindService
- Service只能被创建一次,onCreate()和onBind()方法会被调用一次。
- 多次调用bindService(),onBind()方法并不会被多次调用。
android O(8.0)对service影响
满足以下两个条件应用才会受到影响
- 必须在android 8.0以上的设备上
- APP的 targetSdkVersion 配置大于等于26
google为了避免后台应用服务占用大量内存情况,影响前台应用的正常使用,对隐式广播、后台服务进行了限制。
- 应用处于前台时,应用可以自由创建和运行前台与后台 Service。
- 应用进入后台时,在一个持续数分钟的时间窗内,应用仍可以创建和使用 Service。 在
该时间窗结束后,应用将被视为处于空闲状态。- 此时,系统将停止应用的后台 Service,就像应用已经调用 Service 的
Service.stopSelf()方法一样。 - 调用Context.startService() 将引发crash。
- 此时,系统将停止应用的后台 Service,就像应用已经调用 Service 的
根据 google开发者文档--OReo版本后台执行限制 可知
如果满足以下任意条件,应用将被视为处于前台:
- 具有可见 Activity(不管该 Activity 已启动还是已暂停)。
- 具有前台 Service。
- 另一个前台应用已关联到该应用(不管是通过绑定到其中一个 Service,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的 Service,那么该应用处于前台:
- IME
- 壁纸 Service
- 通知侦听器
- 语音或文本 Service
如果以上条件均不满足,应用将被视为处于后台。
在8.0如何以正确的姿势使用
推荐
google推荐使用JobScheduler可以处理大多数的后台任务,如果项目使用了jetpack大礼包,可以使用 google开发者文档--后台处理指南 介绍根据任务类型分别使用 协程、WorkManager、AlarmManager来处理。
使用前台服务(慎重)
在 Android 8.0 之前,创建前台 Service 的方式通常是先创建一个后台 Service,然后将该 Service 推到前台。[startService()]然后在系统创建 Service 后,应用有五秒的时间来调用该 Service 的 startForeground() 方法以显示新 Service 的用户可见通知。 如果应用在此时间限制内未调用 startForeground(),则系统将停止此 Service 并声明此应用为 ANR。
Android 8.0 有一项复杂功能:系统不允许后台应用创建后台 Service。 因此,Android 8.0 引入了一种全新的方法,即 startForegroundService(),以在前台启动新 Service。
使用Application来绑定(取巧)
AIDL进程通信,就是service的一种绑定形式,将主进程Application与Service进行绑定,子进程调用AIDL定义接口方法,从而调用主进程方法,达到通信目的。
IntentService(注意)
IntentService 是一项 Service,因此其遵守针对后台 Service 的新限制。 因此,许多依赖 IntentService 的应用在适配 Android 8.0 或更高版本时无法正常工作。 出于这一原因,Android 支持库 26.0.0 引入了一个新的JobIntentService类,该类提供与 IntentService 相同的功能,但在 Android 8.0 或更高版本上运行时使用作业而非 Service。