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)
Ява
ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);
Затем используйте этот экземпляр, чтобы получить ссылку на текущую сеть по умолчанию для вашего приложения:
Котлин
val currentNetwork = connectivityManager.getActiveNetwork()
Ява
Network currentNetwork = connectivityManager.getActiveNetwork();
Имея ссылку на сеть, ваше приложение может запрашивать информацию о ней:
Котлин
val caps = connectivityManager.getNetworkCapabilities(currentNetwork) val linkProperties = connectivityManager.getLinkProperties(currentNetwork)
Ява
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 может отправлять и получать сообщения службы мультимедийных сообщений, а сеть без этой возможности — нет. Сеть с поддержкой 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) } })
Ява
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)
Ява
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
, если вашему приложению требуется только одноранговое Wi-Fi-подключение. NET_CAPABILITY_INTERNET
и NET_CAPABILITY_VALIDATED
полезны, если вам нужна возможность передачи данных с сервером в Интернете.
Пример последовательности обратного вызова
В этом разделе описывается последовательность обратных вызовов, которые может получить приложение, если оно регистрирует как обратный вызов по умолчанию, так и обычный обратный вызов на устройстве с мобильным подключением. В этом примере устройство подключается к точке доступа Wi-Fi с хорошим сигналом, а затем отключается от неё. В примере также предполагается, что на устройстве включена настройка «Мобильные данные всегда включены».
Хронология выглядит следующим образом:
Когда приложение вызывает
registerNetworkCallback()
, обратный вызов немедленно получает вызовы отonAvailable()
,onNetworkCapabilitiesChanged()
иonLinkPropertiesChanged()
для мобильной сети, поскольку доступна только эта сеть. Если доступна другая сеть, приложение также получает обратные вызовы для этой сети.
Рисунок 1. Состояние приложения после вызоваregisterNetworkCallback()
.Затем приложение вызывает
registerDefaultNetworkCallback()
. Вызов сети по умолчанию начинает получать звонки вonAvailable()
,onNetworkCapabilitiesChanged()
иonLinkPropertiesChanged()
для мобильной сети, поскольку мобильная сеть является сетью по умолчанию. Если другая сеть, не являющаяся деко-по умолчанию.
Рисунок 2. Состояние приложения после регистрации сети по умолчанию.Затем устройство подключается к (безлимитной) сети Wi-Fi. Обратный вызов обычной сети получает вызовы
onAvailable()
,onNetworkCapabilitiesChanged()
иonLinkPropertiesChanged()
для сети Wi-Fi.
Рисунок 3. Состояние приложения после подключения к безлимитной сети Wi-Fi.На этом этапе проверка сети Wi-Fi может занять некоторое время. В этом случае вызовы
onNetworkCapabilitiesChanged()
для обычного обратного вызова сети не включают возможностьNET_CAPABILITY_VALIDATED
. Через некоторое время он получает вызовonNetworkCapabilitiesChanged()
, в котором новые возможности включаютNET_CAPABILITY_VALIDATED
. В большинстве случаев проверка выполняется очень быстро.При проверке сети Wi-Fi система отдаёт ей предпочтение перед мобильной сетью, главным образом потому, что она не тарифицируется. Сеть Wi-Fi становится сетью по умолчанию, поэтому обратный вызов сети по умолчанию получает вызовы
onAvailable()
,onNetworkCapabilitiesChanged()
иonLinkPropertiesChanged()
для сети Wi-Fi. Мобильная сеть переходит в фоновый режим, а обратный вызов обычной сети получает вызовonLosing()
для мобильной сети.Поскольку в этом примере предполагается, что мобильные данные на этом устройстве всегда включены, мобильная сеть никогда не отключается. Если эта настройка отключена, то через некоторое время мобильная сеть отключается, и обычный сетевой обратный вызов получает вызов
onLost()
.
Рисунок 4. Состояние приложения после проверки сети Wi-Fi.Позже устройство внезапно отключается от Wi-Fi, поскольку выходит за пределы зоны действия сети. Из-за отключения Wi-Fi обратный вызов обычной сети получает вызов
onLost()
для Wi-Fi. Поскольку мобильная сеть стала новой сетью по умолчанию, обратный вызов сети по умолчанию получает вызовыonAvailable()
,onNetworkCapabilitiesChanged()
иonLinkPropertiesChanged()
для мобильной сети.
Рисунок 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
, которая должна быть вызвана при подключении к сети.