智能手机的使用寿命内,蜂窝数据套餐的成本很容易超过设备本身的成本。在 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()
检测何时限制电视上的数据使用。
请求数据限制权限
如果您的应用需要在后台使用数据,它可以通过发送包含应用包名称URI的Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS
意图来请求数据限制权限:例如package:MY_APP_ID
。
发送意图和URI会启动**设置**应用并显示您的应用的数据使用设置。然后,用户可以决定是否为您的应用启用后台数据。在发送此意图之前,最好先询问用户是否希望启动**设置**应用以启用后台数据使用。
监控数据节省偏好设置的更改
应用可以通过创建一个BroadcastReceiver
来监听ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED
并使用Context.registerReceiver()
动态注册接收器来监控数据节省偏好设置的更改。当应用接收到此广播时,它应该检查新的数据节省偏好设置是否影响其权限,方法是调用ConnectivityManager.getRestrictBackgroundStatus()
。
注意:系统仅向使用Context.registerReceiver()
动态注册的应用发送此广播。在其清单中注册接收此广播的应用将不会收到此广播。
使用Android Debug Bridge命令进行测试
Android Debug Bridge (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
- 列出所有wifi网络,并显示它们是否为计量网络。
-
$ adb shell cmd netpolicy set metered-network <WIFI_SSID> true
- 将具有指定SSID的wifi设置为计量网络,允许您在非计量网络上模拟计量网络。