Оптимизация для экономии трафика

За время использования смартфона стоимость мобильного интернета может легко превысить стоимость самого устройства. На устройствах с Android 7.0 (уровень API 24) и более поздних версий пользователи могут включить экономию трафика, чтобы оптимизировать его расход. Это особенно полезно в роуминге, в конце платежного цикла или при использовании небольшого предоплаченного пакета трафика.

Если пользователь включит экономию трафика в настройках и устройство будет подключено к сети с тарификацией трафика, система заблокирует передачу данных в фоновом режиме и отправит приложениям сигнал о том, что нужно по возможности сократить объем передаваемых данных в активном режиме. Пользователи могут разрешить определенным приложениям использовать трафик в фоновом режиме, даже если включена экономия трафика.

В Android 7.0 (уровень API 24) расширен API ConnectivityManager, чтобы приложения могли получать настройки экономии трафика и отслеживать их изменения. Рекомендуется проверять, включен ли режим экономии трафика, и ограничивать передачу данных в активном и фоновом режимах.

Проверьте настройки экономии трафика

В Android 7.0 (уровень API 24) и более поздних версиях приложения могут использовать API ConnectivityManager, чтобы определять, какие ограничения на использование трафика применяются. Метод 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 Кбит/с, а в фоновом – 10 Кбит/с. Используйте ConnectivityManager.isActiveNetworkMetered(), чтобы определить, когда нужно ограничить использование данных на телевизоре.

Запрос разрешений на ограничение данных

Если вашему приложению требуется использовать данные в фоновом режиме, оно может запросить разрешение на ограничение данных, отправив намерение Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS, содержащее URI названия пакета приложения, например 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
Показывает полный список команд Network Policy Manager (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>
Удаляет указанный UID пакета из белого списка (whitelist), чтобы заблокировать использование трафика в фоновом режиме, когда включена экономия трафика.
$ adb shell cmd netpolicy list wifi-networks
Показывает список всех сетей Wi-Fi и указывает, являются ли они лимитными.
$ adb shell cmd netpolicy set metered-network <WIFI_SSID> true
Устанавливает для сети Wi-Fi с указанным SSID тарификацию трафика, позволяя имитировать сеть с тарификацией трафика на сети без тарификации.