优化网络流量消耗
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
在智能手机的整个生命周期内,移动数据网络流量套餐的费用往往会超出手机的身价。在 Android 7.0(API 级别 24)和更高版本上,用户可以在整个设备上启用流量节省程序,以优化和减少其设备的流量消耗。当在漫游、结算周期即将结束或使用很小的预付费流量包时,此功能特别有用。
当用户在设置中启用流量节省程序且设备采用按流量计费的网络时,系统会阻止后台流量消耗,并指示应用在前台尽可能减少流量消耗。用户可以允许特定应用使用按流量计费的后台流量消耗,即使在打开流量节省程序时也是如此。
Android 7.0(API 级别 24)扩展了 ConnectivityManager
API,使应用能够检索用户的流量节省程序偏好设置并监控偏好设置的变更。我们建议应用检查用户是否已启用流量节省程序并尽量限制前台和后台流量消耗。
检查流量节省程序偏好设置
在 Android 7.0(API 级别 24)和更高版本上,应用可以使用 ConnectivityManager
API 确定目前所应用的流量消耗限制设置。getRestrictBackgroundStatus()
方法将返回以下某个值:
-
RESTRICT_BACKGROUND_STATUS_DISABLED
-
流量节省程序已停用。
-
RESTRICT_BACKGROUND_STATUS_ENABLED
-
用户已为此应用启用流量节省程序。应用应努力限制前台流量消耗,并妥善处理后台流量消耗限制。
-
RESTRICT_BACKGROUND_STATUS_WHITELISTED
-
用户已启用流量节省程序,但允许该应用绕过此设置。应用应努力限制前台和后台流量消耗。
每当设备连接到按流量计费的网络时都限制流量消耗,即使流量节省程序已停用或允许该应用绕过此设置。以下示例代码使用 ConnectivityManager.isActiveNetworkMetered()
和 ConnectivityManager.getRestrictBackgroundStatus()
确定应用应使用多少流量:
Kotlin
(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {
// Checks if the device is on a metered network
if (isActiveNetworkMetered) {
// Checks user’s Data Saver settings.
when (restrictBackgroundStatus) {
RESTRICT_BACKGROUND_STATUS_ENABLED -> {
// Background data usage is blocked for this app. Wherever possible,
// the app should also use less data in the foreground.
}
RESTRICT_BACKGROUND_STATUS_WHITELISTED -> {
// The app is allowed to bypass Data Saver. Nevertheless, wherever possible,
// the app should use less data in the foreground and background.
}
RESTRICT_BACKGROUND_STATUS_DISABLED -> {
// Data Saver is disabled. Since the device is connected to a
// metered network, the app should use less data wherever possible.
}
}
} else {
// The device is not on a metered network.
// Use data as required to perform syncs, downloads, and updates.
}
}
Java
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// Checks if the device is on a metered network
if (connMgr.isActiveNetworkMetered()) {
// Checks user’s Data Saver settings.
switch (connMgr.getRestrictBackgroundStatus()) {
case RESTRICT_BACKGROUND_STATUS_ENABLED:
// Background data usage is blocked for this app. Wherever possible,
// the app should also use less data in the foreground.
case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
// The app is allowed to bypass Data Saver. Nevertheless, wherever possible,
// the app should use less data in the foreground and background.
case RESTRICT_BACKGROUND_STATUS_DISABLED:
// Data Saver is disabled. Since the device is connected to a
// metered network, the app should use less data wherever possible.
}
} else {
// The device is not on a metered network.
// Use data as required to perform syncs, downloads, and updates.
}
注意:此行为在 Android TV 上有所不同。Android TV 只会节流,而不会阻止后台流量消耗。应用在前台运行时,其流量消耗速率限制在 800 Kbps;应用在后台运行时,其流量消耗速率限制在 10 Kbps。您可以使用 ConnectivityManager.isActiveNetworkMetered()
检测 Android TV 在何时限制流量消耗。
请求流量限制权限
如果您的应用需要在后台消耗流量,它可以发送 Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS
intent 来请求流量限制权限,该 intent 包含您的应用软件包名称的 URI,例如 package:MY_APP_ID
。
发送该 intent 和 URI 时,会启动设置应用,并显示应用的流量消耗设置。用户随后可以决定是否允许您的应用在后台使用流量。在发送此 intent 之前,最好先询问用户是否要为了启用后台流量消耗而启动设置应用。
监控流量节省程序偏好设置的变更
应用可以监控流量节省程序偏好设置的变更,方法是创建一个用于监听 ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED
的 BroadcastReceiver
,并向 Context.registerReceiver()
动态注册该接收器。应用收到此广播后,应调用 ConnectivityManager.getRestrictBackgroundStatus()
来检查新的流量节省程序偏好设置是否会影响其权限。
注意:系统只会将此广播发送给向 Context.registerReceiver()
动态注册以接收此广播的应用。在清单中注册以接收此广播的应用将不会收到此广播。
使用 Android 调试桥命令进行测试
Android 调试桥 (ADB) 提供了一些命令,可用于在流量节省程序条件下测试您的应用。您可以检查和配置网络权限,或者将无线网络设为按流量计费,以便在不按流量计费的网络上测试您的应用。
-
$ adb shell dumpsys netpolicy
-
生成一个报告,其中包括当前全局后台网络限制设置、当前被允许绕过流量节省程序的软件包 UID 以及其他已知软件包的网络权限。
-
$ adb shell cmd netpolicy
-
显示网络政策管理中心 (netpolicy) 命令的完整列表。
-
$ adb shell cmd netpolicy set restrict-background
<boolean>
-
当传入
true
或 false
时,分别启用或停用流量节省程序模式。
-
$ adb shell cmd netpolicy add restrict-background-whitelist
<UID>
-
将指定的软件包 UID 添加到许可名单 (
whitelist
) 中,以允许按流量计费的后台流量消耗。
-
$ adb shell cmd netpolicy remove restrict-background-whitelist
<UID>
-
从许可名单 (
whitelist
) 中移除指定的软件包 UID,在启用了流量节省程序的情况下阻止按流量计费的后台流量消耗。
-
$ adb shell cmd netpolicy list wifi-networks
-
列出所有 Wi-Fi 网络,显示它们是否按流量计费。
-
$ adb shell cmd netpolicy set metered-network <WIFI_SSID>
true
-
将具有指定 SSID 的 Wi-Fi 设为按流量计费,以便在不按流量计费的网络上模拟按流量计费的网络。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-26。
[null,null,["最后更新时间 (UTC):2025-07-26。"],[],[],null,["# Optimize network data usage\n\nOver the life of a smartphone, the cost of a cellular data plan can easily\nexceed the cost of the device itself. On Android 7.0 (API level 24) and\nhigher, users can enable Data Saver on a device-wide basis in order to\noptimize their device's data usage, and use less data. This ability\nis especially useful when roaming, near the end of the billing cycle,\nor for a small prepaid data pack.\n\n\nWhen a user enables Data Saver in **Settings** and the device is\non a metered network, the system blocks background data usage and signals\napps to use less data in the foreground wherever possible. Users can\nallow specific apps to use background metered data usage even when Data\nSaver is turned on.\n\n\nAndroid 7.0 (API level 24) extends the\n[ConnectivityManager](/reference/android/net/ConnectivityManager)\nAPI to provide apps with a way to [retrieve the user's Data\nSaver preferences](#status) and [monitor preference\nchanges](#monitor-changes). It is considered good practice for apps to check whether the\nuser has enabled Data Saver and make an effort to limit foreground and\nbackground data usage.\n\nCheck data saver preferences\n----------------------------\n\n\nOn Android 7.0 (API level 24) and higher, apps can use the\n[ConnectivityManager](/reference/android/net/ConnectivityManager) API\nto determine what data usage restrictions are being applied. The\n[getRestrictBackgroundStatus()](/reference/android/net/ConnectivityManager#getRestrictBackgroundStatus())\nmethod returns one of the following values:\n\n\n`RESTRICT_BACKGROUND_STATUS_DISABLED`\n:\n Data Saver is disabled.\n\n\n`RESTRICT_BACKGROUND_STATUS_ENABLED`\n:\n The user has enabled Data Saver for this app. Apps should make an effort to limit data\n usage in the foreground and gracefully handle restrictions to background\n data usage.\n\n\n`RESTRICT_BACKGROUND_STATUS_WHITELISTED`\n:\n The user has enabled Data Saver but the app is allowed to bypass it.\n Apps should still make an effort to limit foreground and background data usage.\n\n\nLimit data usage whenever the device is connected to a metered network, even if Data Saver is\ndisabled or the app is allowed to bypass it. The following sample code uses\n[ConnectivityManager.isActiveNetworkMetered()](/reference/android/net/ConnectivityManager#isActiveNetworkMetered())\nand `ConnectivityManager.getRestrictBackgroundStatus()` to determine how much data the\napp should use: \n\n### Kotlin\n\n```kotlin\n(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {\n // Checks if the device is on a metered network\n if (isActiveNetworkMetered) {\n // Checks user's Data Saver settings.\n when (restrictBackgroundStatus) {\n RESTRICT_BACKGROUND_STATUS_ENABLED -\u003e {\n // Background data usage is blocked for this app. Wherever possible,\n // the app should also use less data in the foreground.\n }\n RESTRICT_BACKGROUND_STATUS_WHITELISTED -\u003e {\n // The app is allowed to bypass Data Saver. Nevertheless, wherever possible,\n // the app should use less data in the foreground and background.\n }\n RESTRICT_BACKGROUND_STATUS_DISABLED -\u003e {\n // Data Saver is disabled. Since the device is connected to a\n // metered network, the app should use less data wherever possible.\n }\n }\n } else {\n // The device is not on a metered network.\n // Use data as required to perform syncs, downloads, and updates.\n }\n}\n```\n\n### Java\n\n```java\nConnectivityManager connMgr = (ConnectivityManager)\n getSystemService(Context.CONNECTIVITY_SERVICE);\n// Checks if the device is on a metered network\nif (connMgr.isActiveNetworkMetered()) {\n // Checks user's Data Saver settings.\n switch (connMgr.getRestrictBackgroundStatus()) {\n case RESTRICT_BACKGROUND_STATUS_ENABLED:\n // Background data usage is blocked for this app. Wherever possible,\n // the app should also use less data in the foreground.\n\n case RESTRICT_BACKGROUND_STATUS_WHITELISTED:\n // The app is allowed to bypass Data Saver. Nevertheless, wherever possible,\n // the app should use less data in the foreground and background.\n\n case RESTRICT_BACKGROUND_STATUS_DISABLED:\n // Data Saver is disabled. Since the device is connected to a\n // metered network, the app should use less data wherever possible.\n }\n} else {\n // The device is not on a metered network.\n // Use data as required to perform syncs, downloads, and updates.\n}\n```\n\n\n**Note:** This behavior is different on Android TV. Instead of\nblocking background usage, Android TV only throttles it. When in the\nforeground, applications are limited to 800 Kbps, and when in the background,\napplications are limited to 10 Kbps. Use\n`ConnectivityManager.isActiveNetworkMetered()` to detect when to\nlimit data usage on TV.\n\n### Request data restriction permissions\n\n\nIf your app needs to use data in the background, it can request data\nrestriction permissions by sending a\n`Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS`\nintent containing a URI of your app's package name: for example,\n`package:MY_APP_ID`.\n\n\nSending the intent and URI launches the **Settings** app and\ndisplays data usage settings for your app. The user can then decide whether\nto enable background data for your app. Before you send this intent, it is\ngood practice to first ask the user if they want to launch the\n**Settings** app for the purpose of enabling background data\nusage.\n\nMonitor changes to data saver preferences\n-----------------------------------------\n\n\nApps can monitor changes to Data Saver preferences by creating a\n[BroadcastReceiver](/reference/android/content/BroadcastReceiver) to\nlisten for `ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED` and dynamically\nregistering the receiver with\n[Context.registerReceiver()](/reference/android/content/Context#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter)).\nWhen an app receives this broadcast, it should [check if the new Data Saver\npreferences affect its permissions](#status) by calling\n`ConnectivityManager.getRestrictBackgroundStatus()`.\n\n\n**Note:** The system only sends this broadcast to apps that dynamically register for\nthem with\n[Context.registerReceiver()](/reference/android/content/Context#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter)).\nApps that register to receive this broadcast in their manifest will not receive them.\n\nTest with Android Debug Bridge commands\n---------------------------------------\n\n\nThe [Android Debug Bridge (ADB)](/tools/help/adb)\nprovides a few commands that you can use to test your app in Data Saver\nconditions. You can check and configure network\npermissions or set wireless networks as metered to test your app on unmetered\nnetworks.\n\n\n`$ adb shell dumpsys netpolicy`\n:\n Generates a report that includes the current global background network\n restriction setting, package UIDs that are currently allowed to bypass Data Saver, and the\n network permissions of other known packages.\n\n\n`$ adb shell cmd netpolicy`\n:\n Displays a full list of Network Policy Manager (netpolicy) commands.\n\n\n`$ adb shell cmd netpolicy set restrict-background\n\u003cboolean\u003e`\n:\n Enables or disables Data Saver mode when passing `true` or\n `false`, respectively.\n\n\n`$ adb shell cmd netpolicy add restrict-background-whitelist\n\u003cUID\u003e`\n:\n Adds the specified package UID to the allowlist (`whitelist`) to allow background\n metered data usage.\n\n\n`$ adb shell cmd netpolicy remove restrict-background-whitelist\n\u003cUID\u003e`\n:\n Removes the specified package UID from the allowlist (`whitelist`) to block\n background metered data usage while Data Saver is enabled.\n\n\n`$ adb shell cmd netpolicy list wifi-networks`\n:\n Lists all wifi networks, displaying whether they're metered.\n\n\n`$ adb shell cmd netpolicy set metered-network \u003cWIFI_SSID\u003e\ntrue`\n:\n Sets wifi with the specified SSID as metered, allowing you to simulate a\n metered network on an unmetered network."]]