搜索
您的当前位置:首页正文

Android O 后台服务限制

来源:知库网

前言

当应用在后台运行时,仍然会占用系统的内存。如果在后台运行的应用比较多,并且用户正在玩游戏或者看视频的时候,那么很容易会导致系统卡顿。为了提升用户体验,Android O增加了对后台应用的限制。这篇文章将介绍系统对后台应用运行的限制,以及开发者应该如果修改应用以适应这个限制。

概述

在Android系统中,很多应用和服务是可以同时运行的。比如说,用户可以在一个窗口中玩游戏,在另一个窗口中浏览网页,同时使用第三个应用来听音乐。同时运行的应用越多,系统的负载就越大。如果又有其他的应用或者服务在后台运行的话,那么又会增加系统的负载,最后导致系统卡顿,影响到用户体验,比如正在播放的音乐会突然停顿。

为了减少系统卡顿,Android O限制那些用户不再直接交互应用的运行。针对targetSdkVersion是Android O的应用,Android增加了以下两种方式的限制:

  • 后台服务(Background Service)限制:当应用处于空闲状态时,后台服务运行会受到限制。但是对于前台服务(Foreground Service),则不会有这个限制,因为前台服务对用户是可见的;
  • 广播(Broadcast)限制:应用不能在manifest文件中注册隐式广播,但是可以在运行时动态注册这些隐式广播。显示广播仍然可以直接在manifest文件中注册;

后台服务限制

后台服务会占用系统资源,这个会导致糟糕的用户体验。为了解决这个问题,Android O对应用的后台服务增加了一堆的限制。注意这些限制仅仅是针对targetSdkVersion为Android O的应用,targetSdkVersion为25或者以下的应用不受影响。

系统会区分前台和后台应用。当满足以下任意一个条件时,系统判定应用是前台的:

  • 有一个可见的Activity,不管这个Activity是已经启动还是暂停的;
  • 有一个前台服务;
  • 另外一个前台应用连接到当前应用,通过bind service或者使用content provider。比如以下情况,应用被其他前台应用绑定了:
    • 输入法
    • Wallpaper service桌面壁纸服务
    • Notification listener
    • Voice or text service语音和文本服务

以上条件都不满足,那么应用就被系统认为是后台应用。

某些情况下,后台应用会被临时加入到白名单中运行几分钟。应用在白名单中时,它可以启动服务而不受限制,并且后台服务也被运行。当需要处理对用户可见的任务时,应用将被添加到白名单中,比如:

  • 处理高优先级的推送消息;
  • 接收到广播,比如有新的短信;
  • 系统通知中通过PendingIntent调起应用的组件;

广播限制

如果应用注册了广播,那么只要有广播发送,应用的广播接收器就会自动运行,占用系统资源。当很多应用都注册了某个系统事件广播时,那么就会出现性能问题,因为当系统事件触发广播时所有的应用的接收器在很短的时间内都会被顺序运行,这样就会影响用户体验。为了解决这个问题,Android 7.0增加了对广播的限制。Android O进一步加强了这个限制。

  • 应用不允许在Manifest文件中注册隐式广播。隐式广播是指不会定向发送的广播。比如,是一个隐式广播,由于它会被发送给所有注册了这个广播的监听器,通知手机上的某个安装包被替换了。不是隐式广播,由于它只会发送给安装包被替换的那个应用,而其他注册了这个广播的应用不会接受到;
  • 应用可以继续在Manifest文件注册显示广播;
  • 应用可以使用[Context.registerReceiver](, android.content.IntentFilter))在运行注册显示或者隐式广播;

升级指南

上面介绍的这些变化不会影响到targetSdkVersion是25或者以下的应用 。但是如果应用是targetSdkVersion是Android O对应的API级别,需要修改应用以遵守这些新的限制。
如果应用在空闲状态仍然在运行后台服务,那么你需要替换掉这些后台服务。可以采用如下的方案:

  • 应用在后台时调用[NotificationManager.startServiceInForeground()](, int, android.app.Notification))创建前台服务;
  • 如果一个服务会被用户看到,那么将这个服务变成前台服务。比如,播放音乐的服务应该是一个前台服务,那么使用[NotificationManager.startServiceInForeground()](, int, android.app.Notification))创建这个服务而不是;
  • 使用调度的Job替换掉后台服务;
  • 当网络事件发生时,使用选择性唤醒你的应用,而不是在后台轮询;
  • 延迟需要后台运行的任务,直到应用被用户打开,在前台运行;

检查在Manifest注册的广播,替换掉隐式广播:

  • 在运行时使用[Context.registerReceiver()](, android.content.IntentFilter))动态注册隐式广播;
  • 使用的Job来替换隐式广播;
Top