系统对后台工作的限制

后台进程可能会耗费大量内存和电池电量。例如, 隐式广播可能会启动许多已注册到 并监听,即使这些进程可能没有很多工作。这种类型 对设备性能和用户体验产生重大影响。

为避免受到系统限制,请确保使用正确的 API, 后台任务。通过 后台任务概览文档可帮助您 找到适合您需求的 API。

用户发起的限制

如果应用出现 Android Vitals 中所述的一些不良行为, 系统会提示用户限制该应用对系统资源的访问权限。

如果系统发现应用消耗的资源过多,则会通知 用户,并为用户提供限制应用操作的选项。 可触发此类通知的行为包括:

  1. 唤醒锁定次数过多:屏幕处于以下状态时,1 次部分唤醒锁定会保持 1 小时 停用
  2. 后台服务过多:如果应用以低于 26 的 API 级别为目标平台 并且包含过多的后台服务

施加的确切限制由设备制造商决定。对于 例如,在 AOSP build 中,受限应用无法运行作业、触发警报或使用 除非应用在前台运行。

对接收网络活动广播的限制

应用不会收到 CONNECTIVITY_ACTION 广播,它们注册到 在其清单中接收它们,以及依赖于此广播的进程 无法启动。这可能会给要监听网络的应用带来问题 更改,或在设备连接到 不按流量计费的网络目前有几种解决方案可绕过此限制 都属于 Android 框架,但要选择合适的框架, 您希望应用能完成哪些操作

在不按流量计费的网络时调度工作

构建 WorkRequest 时,请添加 NetworkType.UNMETERED Constraint

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
       .setConstraints(
           Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .build()
           )
       .build()

    workManager.enqueue(workRequest)
}

当满足工作条件时,您的应用会收到一个回调以运行 指定的 Worker 类中的 doWork() 方法。

在应用运行时监控网络连接

正在运行的应用仍可以通过CONNECTIVITY_CHANGE 已注册“BroadcastReceiver”。但是,ConnectivityManager API 提供了一种更可靠的方法,仅在指定网络时请求回调 条件。

NetworkRequest 对象在 NetworkCapabilities 的条款。您创建 NetworkRequest 对象 与 NetworkRequest.Builder 类相关联。registerNetworkCallback 然后,将 NetworkRequest 对象传递给系统。当网络 条件满足后,应用会收到回调以执行 onAvailable() 方法(在其 ConnectivityManager.NetworkCallback 类。

应用会继续接收回调,直到应用退出或调用 unregisterNetworkCallback()

对接收图片和视频广播的限制

应用无法发送或接收 ACTION_NEW_PICTUREACTION_NEW_VIDEO 广播。此限制有助于缓解 性能和用户体验会影响何时必须唤醒多个应用 处理新图片或视频

确定哪些内容授权方触发了工作

WorkerParameters 可让应用接收有关哪些应用/游戏的 的内容授权方和 URI 会触发相应工作:

List<Uri> getTriggeredContentUris()

返回已触发工作的 URI 列表。如果存在以下情况,则此字段为空 没有 URI 触发工作(例如,工作因 截止时间或某种其他原因),或者更改的 URI 数量超过 50。

List<String> getTriggeredContentAuthorities()

返回已触发工作的内容授权方的字符串列表。如果 返回的列表不为空,请使用 getTriggeredContentUris() 检索 更改的 URI 的详细信息。

以下示例代码替换了 CoroutineWorker.doWork() 方法 并记录已触发作业的内容授权方和 URI:

class MyWorker(
    appContext: Context,
    params: WorkerParameters
): CoroutineWorker(appContext, params)
    override suspend fun doWork(): Result {
        StringBuilder().apply {
            append("Media content has changed:\n")
            params.triggeredContentAuthorities
                .takeIf { it.isNotEmpty() }
                ?.let { authorities ->
                    append("Authorities: ${authorities.joinToString(", ")}\n")
                    append(params.triggeredContentUris.joinToString("\n"))
                } ?: append("(No content)")
            Log.i(TAG, toString())
        }
        return Result.success()
    }
}

在系统限制下测试应用

优化您的应用,使其能够在低内存设备上运行,或在内存不足的条件下运行; 可以改善性能和用户体验。移除后台依赖项 服务和清单注册的隐式广播接收器可以帮助您的应用 在此类设备上运行得更好。建议您优化应用 而不必使用这些后台进程

其他一些 Android 调试桥 (ADB) 命令可以帮助您测试应用 停用这些后台进程时的行为:

  • 为了模拟隐式广播和后台服务 找不到,请输入以下命令:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • 要重新启用隐式广播和后台服务,请输入以下内容 命令:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

进一步优化应用

如需了解优化后台任务的其他有效方法行为,请参见 优化任务调度 API 的电池使用情况 文档。