优化网络流量消耗

在智能手机的整个生命周期内,移动数据网络流量套餐的费用往往会超出设备本身的成本。从 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 whitelisted. 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 whitelisted. 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.
    }
    

请求白名单权限

如果您的应用需要在后台消耗流量,它可以发送 Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS intent 来请求白名单权限,该 intent 包含您的应用的软件包名称的 URI,例如 package:MY_APP_ID

发送该 intent 和 URI 时,会启动设置应用,并显示您的应用的流量消耗设置。用户随后可以决定是否为您的应用启用后台流量。在发送此 intent 之前,最好先询问用户是否要启动设置应用,以便启用后台流量消耗。

监控流量节省程序偏好设置更改

应用可以监控流量节省程序偏好设置的更改,方法是创建一个 BroadcastReceiver 来监听 ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED,并向 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>
当传递 truefalse 时,分别启用或停用流量节省程序模式。
$ adb shell cmd netpolicy add restrict-background-whitelist <UID>
将指定的软件包 UID 添加到白名单,以允许按流量计费的后台流量消耗。
$ adb shell cmd netpolicy remove restrict-background-whitelist <UID>
从白名单中移除指定的软件包 UID,在启用了流量节省程序的情况下阻止按流量计费的后台流量消耗。
$ adb shell cmd netpolicy list wifi-networks
列出所有 WLAN 网络,显示它们是否按流量计费。
$ adb shell cmd netpolicy set metered-network <WIFI_SSID> true
将具有指定 SSID 的 WLAN 设为按流量计费,以便在不按流量计费的网络上模拟按流量计费的网络。