Чтение состояния сети

Android позволяет приложениям отслеживать динамические изменения в подключении. Используйте следующие классы для отслеживания изменений в подключении и реагирования на них:

  • ConnectivityManager сообщает вашему приложению о состоянии подключения к сети в системе.
  • Класс Network представляет одну из сетей, к которым подключено устройство. Вы можете использовать объект Network в качестве ключа для сбора информации о сети с помощью ConnectivityManager или для привязки сокетов в сети. При разрыве соединения объект Network перестает быть доступным. Даже если устройство позже повторно подключится к тому же устройству, новый объект Network будет представлять новую сеть.
  • Объект LinkProperties содержит информацию о канале связи в сети, такую ​​как список DNS-серверов, локальные IP-адреса и сетевые маршруты, установленные для сети.
  • Объект NetworkCapabilities содержит информацию о свойствах сети, таких как используемые протоколы передачи данных (Wi-Fi, мобильная связь, Bluetooth) и возможности сети. Например, вы можете запросить этот объект, чтобы определить, может ли сеть отправлять MMS, находится ли она за авторизационным порталом или является тарифицируемой.

Приложения, заинтересованные в текущем состоянии подключения в любой момент времени, могут вызывать методы ConnectivityManager , чтобы узнать, какой тип сети доступен. Эти методы полезны для отладки и для периодического просмотра снимка доступного подключения в любой момент времени.

Однако синхронные методы ConnectivityManager не сообщают вашему приложению о каких-либо событиях, происходящих после вызова, поэтому они не позволяют обновлять пользовательский интерфейс. Они также не могут корректировать поведение приложения в зависимости от разрыва сетевого соединения или изменения сетевых возможностей.

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

Использование NetworkCallback и других способов получения информации о состоянии подключения устройства не требует каких-либо особых разрешений. Однако для некоторых сетей могут потребоваться специальные разрешения. Например, могут существовать сети с ограниченным доступом, недоступные для приложений. Для подключения к фоновой сети требуется разрешение CHANGE_NETWORK_STATE . А для выполнения некоторых вызовов могут потребоваться специальные разрешения. Для получения подробной информации обратитесь к документации по каждому вызову.

Получить мгновенное состояние

Устройство под управлением Android может поддерживать множество соединений одновременно. Чтобы получить информацию о текущем состоянии сети, сначала получите экземпляр ConnectivityManager :

Котлин

val connectivityManager = getSystemService(ConnectivityManager::class.java)

Java

ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);

Далее, используйте этот экземпляр, чтобы получить ссылку на текущую сеть по умолчанию для вашего приложения:

Котлин

val currentNetwork = connectivityManager.getActiveNetwork()

Java

Network currentNetwork = connectivityManager.getActiveNetwork();

Имея ссылку на сеть, ваше приложение может запросить информацию о ней:

Котлин

val caps = connectivityManager.getNetworkCapabilities(currentNetwork)
val linkProperties = connectivityManager.getLinkProperties(currentNetwork)

Java

NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(currentNetwork);
LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);

Для расширения функциональности зарегистрируйте объект NetworkCallback . Дополнительную информацию о регистрации сетевых обратных вызовов см. в разделе «Прослушивание сетевых событий» .

Возможности сети и свойства каналов

Объекты NetworkCapabilities и LinkProperties предоставляют информацию обо всех атрибутах, известных системе о сети.

Объект LinkProperties содержит информацию о маршрутах, адресах каналов связи, имени интерфейса, информации о прокси-серверах (если таковая имеется) и DNS-серверах. Вызовите соответствующий метод объекта LinkProperties , чтобы получить необходимую информацию.

Объект NetworkCapabilities содержит информацию о сетевых протоколах и их возможностях .

Транспорт — это абстракция физической среды, по которой работает сеть. Распространенные примеры транспортных протоколов — Ethernet, Wi-Fi и мобильная связь. VPN и одноранговые сети Wi-Fi также могут быть транспортными протоколами. На Android сеть может одновременно использовать несколько транспортных протоколов. Примером может служить VPN, работающий как по Wi-Fi, так и по мобильной сети. VPN имеет транспортные протоколы Wi-Fi, мобильной связи и VPN. Чтобы узнать, использует ли сеть определенный транспортный протокол, используйте метод NetworkCapabilities.hasTransport(int) с одной из констант NetworkCapabilities.TRANSPORT_* .

Возможность описывает свойство сети. Примеры возможностей включают MMS , NOT_METERED и INTERNET . Сеть с возможностью MMS может отправлять и получать сообщения службы мультимедийных сообщений (MMS), а сеть без этой возможности — нет. Сеть с возможностью NOT_METERED не взимает плату с пользователя за передачу данных. Ваше приложение может проверить наличие соответствующих возможностей, используя метод NetworkCapabilities.hasCapability(int) с одной из констант NetworkCapabilities.NET_CAPABILITY_* .

К наиболее полезным константам NET_CAPABILITY_* относятся:

  • NET_CAPABILITY_INTERNET : указывает, что сеть настроена для доступа к интернету. Это касается настройки , а не фактической возможности доступа к общедоступным серверам. Например, сеть может быть настроена для доступа к интернету, но при этом использовать портал авторизации.

    Мобильная сеть оператора связи обычно обладает возможностью подключения INTERNET , в то время как локальная P2P-сеть Wi-Fi, как правило, такой возможности не имеет. Для получения информации о фактическом подключении см. NET_CAPABILITY_VALIDATED .

  • NET_CAPABILITY_NOT_METERED : указывает, что сеть не является тарифицируемой. Сеть классифицируется как тарифицируемая, если пользователь чувствителен к интенсивному использованию данных в этом соединении из-за финансовых затрат, ограничений по объему данных или проблем с производительностью батареи.

  • NET_CAPABILITY_NOT_VPN : указывает, что сеть не является виртуальной частной сетью.

  • NET_CAPABILITY_VALIDATED : указывает, что сеть фактически обеспечивает доступ к общедоступному интернету при проверке. Сеть, находящаяся за авторизационным порталом или не предоставляющая разрешение доменных имен, не обладает этой возможностью. Это наиболее точная информация, которую система может предоставить о фактическом доступе к сети, хотя проверенная сеть, в принципе, все еще может подвергаться фильтрации по IP-адресам или внезапно терять связь из-за таких проблем, как слабый сигнал.

  • NET_CAPABILITY_CAPTIVE_PORTAL : указывает, что в сети при проверке присутствует портал авторизации.

Существуют и другие возможности, которые могут заинтересовать более специализированные приложения. Для получения дополнительной информации ознакомьтесь с определениями параметров в NetworkCapabilities.hasCapability(int) .

Функциональные возможности сети могут изменяться в любой момент. Когда система обнаруживает авторизацию через портал авторизации, она отображает уведомление с приглашением пользователя войти в систему. В это время сеть обладает правами доступа NET_CAPABILITY_INTERNET и NET_CAPABILITY_CAPTIVE_PORTAL но не имеет прав доступа NET_CAPABILITY_VALIDATED .

Когда пользователь совершает действие и входит на страницу авторизации, устройство получает доступ к общедоступному интернету, сеть приобретает возможность NET_CAPABILITY_VALIDATED и теряет возможность NET_CAPABILITY_CAPTIVE_PORTAL .

Аналогично, транспортные протоколы сети могут динамически изменяться. Например, VPN может перенастроиться для использования более быстрой сети, которая только что появилась, например, переключившись с мобильной связи на Wi-Fi в качестве базовой сети. В этом случае сеть теряет транспортный протокол TRANSPORT_CELLULAR и получает транспортный протокол TRANSPORT_WIFI , сохраняя при этом транспортный протокол TRANSPORT_VPN .

Слушайте новости сетевых мероприятий

Чтобы узнать о сетевых событиях, используйте класс NetworkCallback вместе с ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback) и ConnectivityManager.registerNetworkCallback(NetworkCallback) . Эти два метода служат разным целям.

Все приложения для Android имеют сеть по умолчанию, которая определяется системой. Как правило, система отдает предпочтение безлимитным сетям перед лимитированными и более быстрым сетям перед более медленными.

Когда приложение отправляет сетевой запрос, например, с помощью HttpsURLConnection , система удовлетворяет этот запрос, используя сеть по умолчанию. Приложения также могут отправлять трафик через другие сети. Для получения дополнительной информации см. раздел о дополнительных сетях .

Сеть, установленная в качестве сети по умолчанию, может меняться в любое время в течение жизненного цикла приложения. Типичный пример: устройство оказывается в зоне действия известной, активной, безлимитной точки доступа Wi-Fi со скоростью выше мобильной. Устройство подключается к этой точке доступа и переключает сеть по умолчанию для всех приложений на новую сеть Wi-Fi.

Когда новая сеть становится сетью по умолчанию, любое новое соединение, открываемое приложением, использует эту сеть. Через некоторое время все оставшиеся соединения в предыдущей сети по умолчанию принудительно разрываются. Если приложению важно знать об изменении сети по умолчанию, оно регистрирует обратный вызов для сети по умолчанию следующим образом:

Котлин

connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network : Network) {
        Log.e(TAG, "The default network is now: " + network)
    }

    override fun onLost(network : Network) {
        Log.e(TAG, "The application no longer has a default network. The last default network was " + network)
    }

    override fun onCapabilitiesChanged(network : Network, networkCapabilities : NetworkCapabilities) {
        Log.e(TAG, "The default network changed capabilities: " + networkCapabilities)
    }

    override fun onLinkPropertiesChanged(network : Network, linkProperties : LinkProperties) {
        Log.e(TAG, "The default network changed link properties: " + linkProperties)
    }
})

Java

connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        Log.e(TAG, "The default network is now: " + network);
    }

    @Override
    public void onLost(Network network) {
        Log.e(TAG, "The application no longer has a default network. The last default network was " + network);
    }

    @Override
    public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
        Log.e(TAG, "The default network changed capabilities: " + networkCapabilities);
    }

    @Override
    public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
        Log.e(TAG, "The default network changed link properties: " + linkProperties);
    }
});

Когда новая сеть становится сетью по умолчанию, приложение получает вызов метода onAvailable(Network) для этой новой сети. Реализуйте onCapabilitiesChanged(Network,NetworkCapabilities) , onLinkPropertiesChanged(Network,LinkProperties) или оба метода, чтобы адекватно реагировать на изменения в подключении.

Для функции обратного вызова, зарегистрированной с помощью registerDefaultNetworkCallback() , onLost() означает, что сеть утратила статус сети по умолчанию. Возможно, произошло отключение.

Хотя вы можете узнать о транспортных протоколах, используемых сетью по умолчанию, запросив NetworkCapabilities.hasTransport(int) , это плохой показатель пропускной способности или тарификации сети. Ваше приложение не может предполагать, что Wi-Fi всегда бесплатен и всегда обеспечивает лучшую пропускную способность, чем мобильная связь.

Вместо этого используйте NetworkCapabilities.getLinkDownstreamBandwidthKbps() для измерения пропускной способности и NetworkCapabilites.hasCapability(int) с аргументом NET_CAPABILITY_NOT_METERED для определения степени учета трафика. Для получения дополнительной информации см. раздел о NetworkCapabilities и LinkProperties .

По умолчанию методы обратного вызова вызываются в потоке подключения вашего приложения, который является отдельным потоком, используемым ConnectivityManager . Если вашей реализации обратных вызовов требуется выполнять более длительную работу, вызывайте их в отдельном рабочем потоке, используя вариант ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler) .

Отмените регистрацию обратного вызова, когда он вам больше не нужен, вызвав метод ConnectivityManager.unregisterNetworkCallback(NetworkCallback) . Для этого хорошо подойдет onPause() в главном окне активности, особенно если вы регистрируете обратный вызов в onResume() .

Дополнительные сети (расширенные варианты использования)

Хотя для большинства приложений подходит только сеть по умолчанию, некоторым приложениям могут быть интересны и другие доступные сети. Чтобы узнать о них, приложения создают NetworkRequest , соответствующий их потребностям, и вызывают ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback) .

Процесс похож на прослушивание сети по умолчанию. Однако, хотя для приложения в любой момент времени может существовать только одна сеть по умолчанию, эта версия позволяет вашему приложению одновременно видеть все доступные сети, поэтому вызов onLost(Network) означает, что сеть окончательно разорвана, а не то, что она больше не является сетью по умолчанию.

Приложение формирует объект NetworkRequest , чтобы сообщить ConnectivityManager , к каким типам сетей оно хочет подключаться. В следующем примере показано, как сформировать объект NetworkRequest для приложения, которое интересуется только безлимитными интернет-соединениями:

Котлин

val request = NetworkRequest.Builder()
  .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
  .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
  .build()

connectivityManager.registerNetworkCallback(request, myNetworkCallback)

Java

NetworkRequest request = new NetworkRequest.Builder()
  .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
  .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
  .build();

connectivityManager.registerNetworkCallback(request, myNetworkCallback);

Это означает, что ваше приложение будет получать информацию обо всех изменениях, касающихся любого безлимитного сетевого трафика в системе.

Что касается стандартного обратного вызова для сети, существует версия функции registerNetworkCallback(NetworkRequest, NetworkCallback, Handler) , которая принимает Handler , поэтому она не загружает поток Connectivity вашего приложения.

Вызывайте ConnectivityManager.unregisterNetworkCallback(NetworkCallback) , когда функция обратного вызова больше не актуальна. Приложение может одновременно регистрировать несколько сетевых функций обратного вызова.

Для удобства объект NetworkRequest содержит общие возможности, необходимые большинству приложений, включая следующие:

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

Например, если вашему приложению необходимо отправлять MMS-сообщения, добавьте NET_CAPABILITY_MMS к NetworkRequest , чтобы избежать уведомлений обо всех сетях, которые не могут отправлять MMS-сообщения. Добавьте TRANSPORT_WIFI_AWARE , если ваше приложение заинтересовано только в P2P-подключении по Wi-Fi. NET_CAPABILITY_INTERNET и NET_CAPABILITY_VALIDATED полезны, если вам нужна возможность передачи данных на сервер в интернете.

Пример последовательности обратных вызовов

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

Хронология событий выглядит следующим образом:

  1. Когда приложение вызывает registerNetworkCallback() , функция обратного вызова немедленно получает вызовы от onAvailable() , onNetworkCapabilitiesChanged() и onLinkPropertiesChanged() для мобильной сети, поскольку доступна только эта сеть. Если доступна другая сеть, приложение также получает обратные вызовы для этой сети.

    Диаграмма состояний, показывающая событие обратного вызова сети регистрации и обратные вызовы, запускаемые этим событием.
    Рисунок 1. Состояние приложения после вызова функции registerNetworkCallback() .

  2. Затем приложение вызывает registerDefaultNetworkCallback() . Коллбэк сети по умолчанию начинает принимать вызовы методов onAvailable() , onNetworkCapabilitiesChanged() и onLinkPropertiesChanged() для мобильной сети, поскольку мобильная сеть является сетью по умолчанию. Если активна другая сеть, не являющаяся сетью по умолчанию, приложение не сможет принимать вызовы для этой сети.

    Диаграмма состояний, показывающая регистрацию события обратного вызова сети по умолчанию и обратные вызовы, запускаемые этим событием.
    Рисунок 2. Состояние приложения после регистрации сети по умолчанию.

  3. Позже устройство подключается к (бесплатной) сети Wi-Fi. Обычный обратный вызов сети получает вызовы функций onAvailable() , onNetworkCapabilitiesChanged() и onLinkPropertiesChanged() для сети Wi-Fi.

    Диаграмма состояний, показывающая обратные вызовы, срабатывающие при подключении приложения к новой сети.
    Рисунок 3. Состояние приложения после подключения к сети Wi-Fi без ограничений трафика.

  4. На данном этапе проверка сети Wi-Fi может занять некоторое время. В этом случае вызовы onNetworkCapabilitiesChanged() для обычного обратного вызова сетевой функции не включают возможность NET_CAPABILITY_VALIDATED . Через короткое время происходит вызов onNetworkCapabilitiesChanged() , в котором новые возможности включают NET_CAPABILITY_VALIDATED . В большинстве случаев проверка проходит очень быстро.

    Когда сеть Wi-Fi проходит проверку, система отдает ей предпочтение перед мобильной сетью, главным образом потому, что она не требует оплаты. Сеть Wi-Fi становится сетью по умолчанию, поэтому функция обратного вызова для сети по умолчанию получает вызовы onAvailable() , onNetworkCapabilitiesChanged() и onLinkPropertiesChanged() для сети Wi-Fi. Мобильная сеть переходит в фоновый режим, и функция обратного вызова для обычной сети получает вызов onLosing() для мобильной сети.

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

    Диаграмма состояний, показывающая обратные вызовы, запускаемые при проверке соединения с сетью Wi-Fi.
    Рисунок 4. Состояние приложения после проверки сети Wi-Fi.

  5. Позже устройство внезапно отключается от Wi-Fi, потому что выходит из зоны действия. Из-за отключения Wi-Fi обычный обратный вызов сети получает вызов onLost() для Wi-Fi. Поскольку мобильная сеть становится новой сетью по умолчанию, обратный вызов сети по умолчанию получает вызовы onAvailable() , onNetworkCapabilitiesChanged() и onLinkPropertiesChanged() для мобильной сети.

    Диаграмма состояний, показывающая обратные вызовы, запускаемые при потере соединения с сетью Wi-Fi.
    Рисунок 5. Состояние приложения после отключения от сети Wi-Fi.

Если функция « Постоянно включенная мобильная передача данных» отключена, то при разрыве соединения Wi-Fi устройство пытается повторно подключиться к мобильной сети. Ситуация аналогична, но с небольшой дополнительной задержкой для вызовов onAvailable() , а обычный обратный вызов для сети также получает вызовы onAvailable() , onNetworkCapabilitiesChanged() и onLinkPropertiesChanged() , поскольку мобильная сеть становится доступной.

Ограничения на использование сети для передачи данных.

Возможность увидеть сеть с помощью функции обратного вызова сети не означает, что ваше приложение может использовать эту сеть для передачи данных. Некоторые сети не предоставляют доступ к интернету, а доступ к некоторым сетям может быть ограничен для привилегированных приложений. Для проверки наличия доступа к интернету см. NET_CAPABILITY_INTERNET и NET_CAPABILITY_VALIDATED .

Использование фоновых сетей также требует проверки разрешений. Если ваше приложение хочет использовать фоновую сеть, ему необходимо разрешение CHANGE_NETWORK_STATE .

Приложения с таким разрешением позволяют системе попытаться подключиться к неактивной сети, например, к мобильной сети, когда устройство подключено к сети Wi-Fi. Такое приложение вызывает метод ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback) , передавая в качестве параметра NetworkCallback , который будет вызван после подключения к сети.