如果您的应用以 Android 11(API 级别 30)或更高版本为目标平台,并且用户几个月未与您的应用互动,系统会将该应用置于“休眠”状态。系统会针对存储空间而非性能进行优化,并保护用户数据。此系统行为与用户通过系统设置手动强行停止应用的操作类似。
休眠的影响
如表 1 所示,休眠的影响取决于应用的目标 SDK 版本以及运行应用的设备:
目标 SDK 版本 | 设备的特征 | 休眠的影响 |
---|---|---|
Android 12 或更高版本 | 搭载 Android 12 或更高版本 |
应用的运行时权限会被重置。此操作与用户在系统设置中查看权限并将应用的访问权限级别更改为拒绝的做法效果一样。 应用无法从后台运行作业或提醒。 应用无法接收推送通知,包括通过 Firebase Cloud Messaging 发送的高优先级消息。 应用缓存中的任何文件都会被移除。 |
Android 11 | 搭载 Android 11 | 应用的运行时权限会被重置。 |
Android 11 | 搭载 Android 6.0(API 级别 23)到 Android 10(API 级别 29)之间的版本(包含这两个版本),且由 Google Play 服务提供支持 |
应用的运行时权限会被重置。 此行为于 2021 年 12 月生效。如需了解详情,请参阅这篇有关为数十亿设备提供自动重置权限功能的博文。 |
应用停止休眠状态时的系统行为
当用户下次与应用互动时,应用会停止休眠状态,并且可以再次创建作业、提醒和通知。
不过,系统不会对应用执行以下操作:
重新授予应用的运行时权限。
用户必须为应用重新授予这些权限。
重新调度在应用进入休眠状态之前调度的所有作业、提醒和通知。
为了更轻松地支持此工作流,请使用 WorkManager。您还可以在
ACTION_BOOT_COMPLETED
广播接收器中添加重新调度逻辑,系统会在您的应用停止休眠状态时以及设备启动后调用它。
应用使用
以下部分提供了应用使用示例,以及系统不会将其视为应用使用的操作示例。
应用使用示例
当应用中的 activity 恢复时,系统会将此事件视为一次用户互动。因此,系统会延长在将应用置于休眠状态之前需要等待的时间。
在 Android 11 及更高版本中,以下行为也会被视为用户互动:
需要注意的是,使用应用休眠时并未明确要求 用户互动只要调用软件包的某个组件,系统就会将其视为应用使用。以下是这方面的一些示例:
- 应用的服务或 content provider 与设备上或 OS 上的其他应用绑定。例如,输入法 (IME) 或密码管理工具。
软件包中的广播接收器接收来自外部软件包的显式广播。
例外情况
如果应用仅表现出下表中的行为,则会在几个月后进入休眠状态:
- 使用
JobScheduler
运行预定作业。 - 接收隐式广播。
- 设置闹钟。
系统级休眠豁免
在某些用例中,Android 会授予系统级权限,让应用免于休眠。如果您的应用属于以下类别之一,该应用将不受应用使用标准的约束,且不会进入休眠状态。
- 应用不在启动器中显示
- 不在启动器中显示有效的快捷方式图块的任何应用。
- 工作资料应用
- 用户在工作资料上安装的任何应用。请注意,如果同一应用还位于个人资料中,只有工作资料上的应用可以免于休眠。
- 设备政策控制器
- 用于控制设备上的本地设备政策和系统应用的应用。
- 运营商特权应用
- 手机运营商在设备上预加载并认为是履行合同服务义务所必需的任何应用,例如语音信箱或客户服务应用。
- 第三方安装程序应用
- 可在必要时自动更新已安装应用的第三方应用商店。
请求用户豁免休眠
如果您预计应用中的核心用例会受到休眠的影响,可以向用户申请豁免,让其准许应用免于休眠。如果用户希望应用主要在后台运行,即使用户不与应用互动,应用也能正常工作,例如,当应用执行以下任一操作时,这种豁免很有用:
- 通过定期报告家庭成员的位置来保障家庭安全。
- 在设备与应用的服务器之间同步数据。
- 与智能设备(如电视)通信。
- 与配套设备(如手表)配对。
如需申请豁免,请完成以下部分中的步骤。
检查用户是否已为应用停用休眠
如需检查用户是否已为应用停用休眠,请使用 getUnusedAppRestrictionsStatus()
API。
如需详细了解如何在应用中使用此 API,请参阅本页中的 API 代码示例。
请求用户为应用停用休眠
如果用户还没有为应用停用休眠,您可以向用户发送请求。为此,请完成以下步骤:
- 显示一个界面,向用户说明他们需要为应用停用休眠的原因。
-
调用
createManageUnusedAppRestrictionsIntent()
API,如 API 代码示例所示。 此 API 会创建一个 intent,用于加载“设置”中的应用信息屏幕。在该页面中,用户可以为应用停用休眠。发送此 intent 时,请务必调用
startActivityForResult()
,而不是startActivity()
。如表 2 所示,该选项的所在位置和名称取决于安装应用的设备的特征:
表 2. 为应用停用休眠的选项 设备的特征 选项所在的页面 用于停用休眠的选项名称 搭载 Android 13 或更高版本 应用信息 暂停未使用应用的活动 搭载 Android 12 应用信息 撤消权限并释放空间 搭载 Android 11 应用信息 > 权限 如果未使用此应用,则移除相关权限 搭载 Android 6.0 到 Android 10 之间的版本(包含这两个版本),且由 Google Play 服务提供支持 Play 应用 > 菜单 > Play 保护机制 > 闲置应用的权限 如果未使用此应用,则移除相关权限
API 代码示例
此代码示例展示了如何检查用户是否已为应用启用休眠,以及请求用户为应用停用休眠的正确方式。
Kotlin
val future: ListenableFuture<Int> = PackageManagerCompat.getUnusedAppRestrictionsStatus(context) future.addListener({ onResult(future.get()) }, ContextCompat.getMainExecutor(context)) fun onResult(appRestrictionsStatus: Int) { when (appRestrictionsStatus) { // Couldn't fetch status. Check logs for details. ERROR -> { } // Restrictions don't apply to your app on this device. FEATURE_NOT_AVAILABLE -> { } // The user has disabled restrictions for your app. DISABLED -> { } // If the user doesn't start your app for a few months, the system will // place restrictions on it. See the API_* constants for details. API_30_BACKPORT, API_30, API_31 -> handleRestrictions(appRestrictionsStatus) } } fun handleRestrictions(appRestrictionsStatus: Int) { // If your app works primarily in the background, you can ask the user // to disable these restrictions. Check if you have already asked the // user to disable these restrictions. If not, you can show a message to // the user explaining why permission auto-reset or app hibernation should be // disabled. Then, redirect the user to the page in system settings where they // can disable the feature. val intent = IntentCompat.createManageUnusedAppRestrictionsIntent(context, packageName) // You must use startActivityForResult(), not startActivity(), even if // you don't use the result code returned in onActivityResult(). startActivityForResult(intent, REQUEST_CODE) }
旧版平台 API
操作系统还包含用于与休眠功能交互的 API。但是,此 API 仅适用于搭载 Android 11 或更高版本的设备;它不能处理向后移植到较低 Android 版本的休眠功能。因此,我们不建议您使用此 API。
如果您需要暂时继续使用此 API 以确保兼容性,请查看以下列表了解使用方式:
- 如需检查用户是否已为应用停用休眠:请使用
isAutoRevokeWhitelisted()
- 如需将用户转至休眠设置页面:请使用
ACTION_APPLICATION_DETAILS_SETTINGS
创建 intent
手动调用休眠行为
如需测试应用在系统将其置于休眠状态后的行为,请完成以下步骤:
(仅限 Android 12 及更高版本)在设备上启用休眠行为:
adb shell device_config put app_hibernation app_hibernation_enabled true
设置系统在将应用置于休眠状态之前需要等待的默认时长。这样,您就可以在测试后恢复此设置:
threshold=$(adb shell device_config get permissions \ auto_revoke_unused_threshold_millis2)
缩短系统需要等待的时长。下面的示例对系统进行了修改,这样一来,当您停止与应用互动后仅一秒钟,系统就会将应用置于休眠状态:
adb shell device_config put permissions \ auto_revoke_unused_threshold_millis2 1000
通过运行以下命令,等待测试设备上启动期间的所有广播完成:
adb shell am wait-for-broadcast-idle
广播完成后,此命令将返回以下消息:
All broadcast queues are idle!
手动调用应用休眠流程:
adb shell cmd jobscheduler run -u 0 -f \ com.google.android.permissioncontroller 2
(仅限 Android 12 及更高版本)使用以下方法之一确认应用已休眠:
- 请注意,测试设备现在会显示一条通知,表明未使用的应用已休眠。
运行以下命令:
adb shell cmd app_hibernation get-state PACKAGE-NAME
恢复系统在将应用置于休眠状态之前需要等待的默认时长:
adb shell device_config put permissions \ auto_revoke_unused_threshold_millis2 $threshold