在智能手机的使用寿命中,蜂窝数据套餐的成本很容易超过设备本身的成本。在 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()
检测何时限制 TV 上的数据使用。
请求数据限制权限
如果您的应用程序需要在后台使用数据,它可以通过发送包含应用程序包名称 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 调试桥 (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 设置为计量网络,允许您在非计量网络上模拟计量网络。