知识点补全1:Service启动bind和start方式区别以及android O(8.0)对service的影响

380 阅读5分钟

google开发者文档是最好的老师,网络上文章大多是个人解读,因人而异。 google开发者文档--服务概览

google开发者文档--后台处理指南

google开发者文档--OReo版本后台执行限制

Service介绍

Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件,从服务类型上看有以下三种:

  1. 前台服务:前台服务执行一些用户能注意到的操作,前台服务必须显示,即使用户停止与应用的交互,前台服务仍会继续运行。(例如 网易云音乐播放音乐,迅雷下载,即使应用处于后台,前台仍会有长时间驻留通知)
  2. 后台服务:后台服务执行用户不会直接注意到的操作。(例如后台压缩文件)
    • 需要注意的是android O开始对后台服务进行限制,app处于空闲期会停止正在运行的后台服务,所以google推荐使用JobScheduler可以处理大多数的后台任务,如果项目使用了jetpack大礼包,可以使用 google开发者文档--后台处理指南 介绍根据任务类型分别使用 协程WorkManagerAlarmManager来处理。
  3. 绑定服务:当应用组件通过调用 bindService() 绑定到服务时,服务即处于绑定状态。
    • 绑定服务会提供客户端-服务器接口,以便组件与服务进行交互、发送请求、接收结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。
    • 仅当与另一个应用组件绑定时,绑定服务才会运行。
    • 多个组件可同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

从启动的方式上看有2种方式

  1. start方式

    • 该服务在其他组件调用 startService() 时创建,然后无限期运行,且必须通过调用 stopSelf() 来自行停止运行。此外,其他组件也可通过调用 stopService() 来停止此服务。服务停止后,系统会将其销毁。
  2. bind方式

    • 该服务在其他组件(客户端)调用 bindService() 时创建。然后,客户端通过 IBinder 接口与服务进行通信。客户端可通过调用 unbindService() 关闭连接。多个客户端可以绑定到相同服务,而且当所有绑定全部取消后,系统即会销毁该服务。(服务不必自行停止运行。) 需要注意的是 这两种方式并不互斥即可以start方式并且bind方式启动一个service(例如 播放音乐服务 即 让其服务无限期运行并同时提供绑定很有用处,应用处于后台时,这是一个前台服务可以长久运行,应用来到前台时也要和控制界面进行绑定,以此来控制播放器,此类情况下,在所有客户端取消绑定之前,stopService() 或 stopSelf() 实际不会停止服务)

俩种方式的生命周期如下图所示

google开发者文档图片--service两种启动方式生命周期

对于多次调用解惑

  1. startService

    • Service只能被创建一次,即onCreate()方法只会被调用一次。
    • 每次调用startService(),onStartCommand()方法都会被调用(onStart方法在API 5时被废弃)。
  2. bindService

    • Service只能被创建一次,onCreate()和onBind()方法会被调用一次。
    • 多次调用bindService(),onBind()方法并不会被多次调用。

android O(8.0)对service影响

满足以下两个条件应用才会受到影响

  • 必须在android 8.0以上的设备上
  • APP的 targetSdkVersion 配置大于等于26

google为了避免后台应用服务占用大量内存情况,影响前台应用的正常使用,对隐式广播、后台服务进行了限制。

  1. 应用处于前台时,应用可以自由创建和运行前台与后台 Service。
  2. 应用进入后台时,在一个持续数分钟的时间窗内,应用仍可以创建和使用 Service。 在该时间窗结束后,应用将被视为处于空闲状态。
    • 此时,系统将停止应用的后台 Service,就像应用已经调用 Service 的 Service.stopSelf() 方法一样。
    • 调用Context.startService() 将引发crash。

根据 google开发者文档--OReo版本后台执行限制 可知

如果满足以下任意条件,应用将被视为处于前台:

  • 具有可见 Activity(不管该 Activity 已启动还是已暂停)。
  • 具有前台 Service。
  • 另一个前台应用已关联到该应用(不管是通过绑定到其中一个 Service,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的 Service,那么该应用处于前台:
    • IME
    • 壁纸 Service
    • 通知侦听器
    • 语音或文本 Service

如果以上条件均不满足,应用将被视为处于后台。

在8.0如何以正确的姿势使用

推荐

google推荐使用JobScheduler可以处理大多数的后台任务,如果项目使用了jetpack大礼包,可以使用 google开发者文档--后台处理指南 介绍根据任务类型分别使用 协程WorkManagerAlarmManager来处理。

使用前台服务(慎重)

在 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。