Android 8.0后台运行策略学习

本文主要是对谷歌开发者官方微信公众号发布的【中文教学视频】Android Oreo 中的后台进程等文章的学习记录。

为了流畅的用户体验,从 API 26开始,Android 对后台服务引入了严格的限制。基本上,除非应用在前台运行,否则系统将在几分钟内停止应用的所有后台服务(2018年2月8日:经笔者在Nexus 5X、Android系统版本8.1下测试,实际能停留的时间只有一分钟)。
这里写图片描述

概览

  • Service+广播: 面向O+ 或者用户选择启用
  • Service
    • 不能在后台启动Service:
      • 无startService
      • 不能向pendingIntent封装Service发送信息
      • 从前台到后台: Service关闭
      • 从后 台 到 前 台: startForegroundService
  • 广播
    • 不能在清单中注册隐式广播
    • 存在一个简短的白名单
  • 位置
    • 影响所有目标平台的应用

Service限制

将影响通过隐式广播启动的应用和从后台启动服务的应用
从后台调用startService,将触发IllegalStateException异常。

前台应用的定义

  • 处于前台的Activity(已启动/暂停)
  • 它具有前台Service。(前台Service创建流程有所变化
  • 另一个前台应用通过绑定或使用内容提供器连接到该应用,如:
    • IME
    • 壁纸Service
    • 通知侦听器
    • 语音或文本Service

影响所有后台Service

包括IntentService、启动服务的PendingIntent(可以创建、但在后台发送时会受影响)、将要提到前台的后台Service(在后台启动并准备提升为前台服务的服务)

针对Service的选项

  • 计划作业JobScheduler
    • FirebaseJobDispatcher
    • JobIntentService(替代IntentService)
  • 临时服务白名单(FCM/GCM)
    下列特殊情形,应用会被列入临时服务白名单,可以在短时间内像在前台一样运行:
    • 高优先级FCM/GCM
    • 短信/彩信传输
    • 来自通知的操作
  • startForegroundService(将始终显示在屏幕上以告知客户正在运行)
    新的创建流程

    1. startForegroundService(Intent service)
    2. 发布优先级至少为LOW的通知
    3. startForeground(int id, Notification notification)

    必须严格按照上面的步骤流程创建前台应用,如果只调用startForegroundService,会出现运行时异常,应用将直接停止运行:

02-08 11:48:51.455 D/AndroidRuntime: Shutting down VM
02-08 11:48:51.457 E/AndroidRuntime: FATAL EXCEPTION: main
                                     Process: com.sy.androidofeatures, PID: 7139
                                     android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
                                         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1768)
                                         at android.os.Handler.dispatchMessage(Handler.java:106)
                                         at android.os.Looper.loop(Looper.java:164)
                                         at android.app.ActivityThread.main(ActivityThread.java:6494)
                                         at java.lang.reflect.Method.invoke(Native Method)
                                         at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
  • 延迟至应用处于前台

adb测试命令

#让应用在后台运行
adb shell am make-uid-idle <package>
#强制允许和禁止后台运行
adb shell cmd appops set <package> RUN_IN_BACKGROUND allow
adb shell cmd appops set <package> RUN_IN_BACKGROUND deny

广播限制

静态定义并监听隐式广播的广播接收器不会接收这些广播
隐式广播:无target component属性
静态接收器:定义于AndroidManifest.xml

针对静态隐式广播接收器的选项

  • 隐式广播限制白名单,参考文末文档
  • 作业JobScheduler
    可适用作业代替的情况:
    • 网络连接变更(按流量计费的网络)
    • 充电状态
    • 观察到内容提供器程序URI发生变化
    • 存储空间过低(8.0新增
    • 电池电量过低(8.0新增
  • 动态广播

后台位置限制

为降低功耗,无论应用的目标 SDK 版本为何,Android 8.0 都会对后台应用检索用户当前位置的频率进行限制。

受影响的 API

  • Fused Location Provider (FLP)
  • Geofencing
  • GNSS Measurements 和 GNSS Navigation Messages
  • Location Manager
    提供给后台应用的位置更新只会根据 Android 8.0 行为变更中定义的间隔,按每小时几次的频率提供。
  • WLAN 管理器
    startScan() 方法对后台应用执行完整扫描的频率仅为每小时数次。如果不久之后后台应用再次调用此方法, WifiManager 类将提供上次扫描所缓存的结果。

相关文档

发布了26 篇原创文章 · 获赞 7 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/China_Style/article/details/79280137