Android umożliwia aplikacjom poznawanie dynamicznych zmian w łączności. Aby śledzić zmiany połączenia i na nie reagować, użyj tych klas:
ConnectivityManager
informuje aplikację o stanie połączenia w systemie.- Klasa
Network
reprezentuje jedną z sieci, z którą połączone jest urządzenie. Możesz użyćNetwork
obiektu jako klucza do zbierania informacji o sieci za pomocąConnectivityManager
lub do wiązania gniazd w sieci. Gdy sieć zostanie odłączona,Network
przestanie być użyteczny. Nawet jeśli urządzenie później ponownie połączy się z tym samym urządzeniem, nowy obiektNetwork
będzie reprezentować nową sieć. - Obiekt
LinkProperties
zawiera informacje o połączeniu sieciowym, takie jak lista serwerów DNS, lokalne adresy IP i trasy sieciowe zainstalowane dla sieci. - Obiekt
NetworkCapabilities
zawiera informacje o właściwościach sieci, takie jak protokoły transportowe (Wi-Fi, komórkowy, Bluetooth) i możliwości sieci. Możesz na przykład wysłać zapytanie do obiektu, aby sprawdzić, czy sieć może wysyłać wiadomości MMS, czy znajduje się za portalem przechwytującym lub czy jest rozliczana według ilości danych.
Aplikacje, które chcą znać bieżący stan połączenia, mogą wywoływać metody ConnectivityManager
, aby sprawdzić, jaki rodzaj sieci jest dostępny. Te metody są przydatne do debugowania i okresowego sprawdzania stanu połączenia w danym momencie.
Metody synchroniczneConnectivityManager
nie informują jednak aplikacji o niczym, co dzieje się po wywołaniu, ConnectivityManager
więc nie pozwalają na aktualizowanie interfejsu. Nie mogą też dostosowywać działania aplikacji w zależności od odłączenia sieci lub zmiany jej możliwości.
Łączność może się zmienić w dowolnym momencie, a większość aplikacji musi mieć zawsze aktualny widok stanu sieci na urządzeniu. Aplikacje mogą rejestrować wywołanie zwrotne w ConnectivityManager
, aby otrzymywać powiadomienia o zmianach, które są dla nich istotne. Dzięki wywołaniu zwrotnemu aplikacja może natychmiast reagować na wszelkie istotne zmiany w połączeniu bez konieczności stosowania kosztownego odpytywania, które może pomijać szybkie aktualizacje.
Korzystanie z NetworkCallback
i innych sposobów sprawdzania stanu połączenia urządzenia nie wymaga żadnych specjalnych uprawnień.
Niektóre sieci podlegają jednak określonym uprawnieniom.
Na przykład mogą istnieć sieci objęte ograniczeniami, które są niedostępne dla aplikacji. Powiązanie z siecią w tle wymaga uprawnienia CHANGE_NETWORK_STATE
. Niektóre wywołania mogą wymagać określonych uprawnień. Szczegółowe informacje znajdziesz w dokumentacji poszczególnych wywołań.
Pobieranie stanu natychmiastowego
Urządzenie z Androidem może utrzymywać wiele połączeń jednocześnie.
Aby uzyskać informacje o bieżącym stanie sieci, najpierw uzyskaj instancję ConnectivityManager
:
Kotlin
val connectivityManager = getSystemService(ConnectivityManager::class.java)
Java
ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);
Następnie użyj tej instancji, aby uzyskać odniesienie do bieżącej domyślnej sieci aplikacji:
Kotlin
val currentNetwork = connectivityManager.getActiveNetwork()
Java
Network currentNetwork = connectivityManager.getActiveNetwork();
Aplikacja może poprosić o informacje o sieci, do której się odwołuje:
Kotlin
val caps = connectivityManager.getNetworkCapabilities(currentNetwork) val linkProperties = connectivityManager.getLinkProperties(currentNetwork)
Java
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(currentNetwork); LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);
Aby uzyskać dostęp do przydatnych funkcji, zarejestruj NetworkCallback
.
Więcej informacji o rejestrowaniu wywołań zwrotnych sieci znajdziesz w artykule Nasłuchiwanie zdarzeń sieciowych.
NetworkCapabilities i LinkProperties
Obiekty NetworkCapabilities
i LinkProperties
zawierają informacje o wszystkich atrybutach sieci, które są znane systemowi.
Obiekt LinkProperties
zawiera informacje o trasach, adresach linków, nazwie interfejsu, informacjach o serwerze proxy (jeśli są dostępne) i serwerach DNS. Wywołaj odpowiednią metodę na obiekcie LinkProperties
, aby pobrać potrzebne informacje.
Obiekt NetworkCapabilities
zawiera informacje o transportach sieci i ich możliwościach.
Transport to abstrakcja medium fizycznego, w którym działa sieć. Typowe przykłady to Ethernet, Wi-Fi i sieć komórkowa.
Transportem mogą być też sieci VPN i Wi-Fi typu peer-to-peer.
Na Androidzie sieć może mieć jednocześnie wiele transportów. Przykładem może być sieć VPN działająca zarówno w sieciach Wi-Fi, jak i komórkowych. Sieć VPN ma transporty Wi-Fi, komórkowy i VPN. Aby sprawdzić, czy sieć ma określony transport, użyj metody NetworkCapabilities.hasTransport(int)
z jedną ze stałych NetworkCapabilities.TRANSPORT_*
.
Możliwość opisuje właściwość sieci. Przykłady funkcji to MMS
, NOT_METERED
i INTERNET
. Sieć z funkcją MMS może wysyłać i odbierać wiadomości MMS, a sieć bez tej funkcji nie może. Sieć z funkcją NOT_METERED
nie obciąża użytkownika za dane. Aplikacja może sprawdzić odpowiednie możliwości za pomocą metody
NetworkCapabilities.hasCapability(int)
z jedną ze stałych NetworkCapabilities.NET_CAPABILITY_*
.
Najbardziej przydatne stałe NET_CAPABILITY_*
to:
NET_CAPABILITY_INTERNET
: oznacza, że sieć jest skonfigurowana do dostępu do internetu. Chodzi o konfigurację, a nie o rzeczywistą możliwość uzyskania dostępu do serwerów publicznych. Na przykład sieć może być skonfigurowana tak, aby mieć dostęp do internetu, ale podlegać portalowi przechwytującemu.Sieć komórkowa operatora zwykle ma taką
INTERNET
możliwość, a lokalna sieć Wi-Fi P2P zwykle nie. Informacje o rzeczywistej łączności znajdziesz w sekcjiNET_CAPABILITY_VALIDATED
.NET_CAPABILITY_NOT_METERED
: oznacza, że sieć nie jest siecią z pomiarem użycia danych. Sieć jest klasyfikowana jako mierzona, gdy użytkownik jest wrażliwy na duże zużycie danych w tym połączeniu ze względu na koszty pieniężne, ograniczenia danych lub problemy z wydajnością baterii.NET_CAPABILITY_NOT_VPN
: oznacza, że sieć nie jest wirtualną siecią prywatną.NET_CAPABILITY_VALIDATED
: oznacza, że sieć zapewnia rzeczywisty dostęp do internetu publicznego podczas testowania. Sieć za portalem uwierzytelniającym lub sieć, która nie zapewnia rozpoznawania nazw domen, nie ma tej możliwości. Jest to najbliższa informacja, jaką system może podać o sieci, która faktycznie zapewnia dostęp. Jednak zweryfikowana sieć może w zasadzie podlegać filtrowaniu na podstawie adresu IP lub nagle utracić łączność z powodu problemów takich jak słaby sygnał.NET_CAPABILITY_CAPTIVE_PORTAL
: wskazuje, że podczas sprawdzania sieć ma portal przechwytujący.
Istnieją inne funkcje, które mogą zainteresować bardziej wyspecjalizowane aplikacje.
Więcej informacji znajdziesz w definicjach parametrów w NetworkCapabilities.hasCapability(int)
.
Możliwości sieci mogą się zmieniać w dowolnym momencie. Gdy system wykryje portal przechwytujący, wyświetli powiadomienie z prośbą o zalogowanie się. W tym czasie sieć ma możliwości NET_CAPABILITY_INTERNET
i NET_CAPABILITY_CAPTIVE_PORTAL
, ale nie ma możliwości NET_CAPABILITY_VALIDATED
.
Gdy użytkownik podejmie działanie i zaloguje się na stronie portalu przechwytującego, urządzenie uzyska dostęp do publicznego internetu, a sieć zyska możliwość NET_CAPABILITY_VALIDATED
i straci możliwość NET_CAPABILITY_CAPTIVE_PORTAL
.
Podobnie transporty sieci mogą się zmieniać dynamicznie.
Na przykład sieć VPN może się przekonfigurować, aby korzystać z szybszej sieci, która właśnie stała się dostępna, np. przełączyć się z sieci komórkowej na Wi-Fi. W tym przypadku sieć traci transport TRANSPORT_CELLULAR
, a zyskuje transport TRANSPORT_WIFI
, zachowując transport TRANSPORT_VPN
.
Nasłuchiwanie zdarzeń sieciowych
Aby dowiedzieć się więcej o zdarzeniach sieciowych, użyj klasy
NetworkCallback
wraz z klasami
ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback)
i
ConnectivityManager.registerNetworkCallback(NetworkCallback)
. Te 2 metody służą różnym celom.
Wszystkie aplikacje na Androida mają domyślną sieć, która jest określana przez system. System zwykle preferuje sieci bez limitu danych od sieci z limitem danych, a szybsze sieci od wolniejszych.
Gdy aplikacja wyśle żądanie sieciowe, np. za pomocą funkcji HttpsURLConnection
, system zrealizuje to żądanie za pomocą sieci domyślnej. Aplikacje mogą też wysyłać ruch w innych sieciach. Więcej informacji znajdziesz w sekcji dotyczącej dodatkowych sieci.
Sieć ustawiona jako domyślna może się zmienić w dowolnym momencie w okresie działania aplikacji. Typowym przykładem jest sytuacja, w której urządzenie znajdzie się w zasięgu znanego, aktywnego, nielimitowanego i szybszego niż sieć komórkowa punktu dostępu Wi-Fi. Urządzenie połączy się z tym punktem dostępu i zmieni domyślną sieć dla wszystkich aplikacji na nową sieć Wi-Fi.
Gdy nowa sieć stanie się domyślną, każde nowe połączenie otwierane przez aplikację będzie korzystać z tej sieci. W późniejszym czasie wszystkie pozostałe połączenia w poprzedniej sieci domyślnej zostaną wymuszone. Jeśli aplikacja musi wiedzieć, kiedy zmienia się sieć domyślna, rejestruje wywołanie zwrotne sieci domyślnej w ten sposób:
Kotlin
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); } });
Gdy nowa sieć stanie się domyślną, aplikacja otrzyma wywołanie funkcji
onAvailable(Network)
dla nowej sieci. Wdróż onCapabilitiesChanged(Network,NetworkCapabilities)
, onLinkPropertiesChanged(Network,LinkProperties)
lub oba te interfejsy, aby odpowiednio reagować na zmiany w połączeniu.
W przypadku wywołania zwrotnego zarejestrowanego za pomocą registerDefaultNetworkCallback()
onLost()
oznacza to, że sieć utraciła status sieci domyślnej. Może być odłączony.
Chociaż możesz dowiedzieć się, jakich transportów używa domyślna sieć, wysyłając zapytanie NetworkCapabilities.hasTransport(int)
, nie jest to dobry sposób na określenie przepustowości ani pomiaru sieci. Aplikacja nie może zakładać, że Wi-Fi zawsze jest bez limitu i zapewnia lepszą przepustowość niż sieć komórkowa.
Zamiast tego używaj
NetworkCapabilities.getLinkDownstreamBandwidthKbps()
do pomiaru przepustowości oraz
NetworkCapabilites.hasCapability(int)
z argumentami
NET_CAPABILITY_NOT_METERED
do określania, czy połączenie jest rozliczane według ilości przesyłanych danych. Więcej informacji znajdziesz w sekcji NetworkCapabilities i LinkProperties.
Domyślnie metody wywołania zwrotnego są wywoływane w wątku łączności aplikacji, który jest oddzielnym wątkiem używanym przez ConnectivityManager
. Jeśli implementacja wywołań zwrotnych wymaga dłuższego działania, wywołuj je w osobnym wątku roboczym, używając wariantu ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler)
.
Jeśli nie potrzebujesz już wywołania zwrotnego, możesz je wyrejestrować, dzwoniąc pod numer ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
.
Najlepiej zrobić to w onPause()
głównej aktywności, zwłaszcza jeśli zarejestrujesz wywołanie zwrotne w onResume()
.
Dodatkowe sieci (zaawansowane przypadki użycia)
Chociaż sieć domyślna jest jedyną odpowiednią siecią w przypadku większości aplikacji, niektóre aplikacje mogą być zainteresowane innymi dostępnymi sieciami. Aby dowiedzieć się więcej o tych aplikacjach, utwórz NetworkRequest
dopasowaną do Twoich potrzeb i wywołaj ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback)
.
Proces jest podobny do nasłuchiwania sieci domyślnej. Chociaż w danym momencie może być tylko jedna sieć domyślna, która ma zastosowanie do aplikacji, ta wersja umożliwia aplikacji jednoczesne wyświetlanie wszystkich dostępnych sieci, więc wywołanie onLost(Network)
oznacza, że sieć została trwale odłączona, a nie że nie jest już domyślna.
Aplikacja tworzy NetworkRequest
, aby poinformować ConnectivityManager
, jakiego rodzaju sieci chce nasłuchiwać. Poniższy przykład pokazuje, jak utworzyć obiekt NetworkRequest
dla aplikacji, która jest zainteresowana tylko połączeniami internetowymi bez limitu danych:
Kotlin
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);
Oznacza to, że aplikacja będzie otrzymywać informacje o wszystkich zmianach dotyczących dowolnej sieci nielimitowanej w systemie.
W przypadku wywołania zwrotnego sieci domyślnej istnieje wersja registerNetworkCallback(NetworkRequest, NetworkCallback, Handler)
, która akceptuje Handler
, dzięki czemu nie wczytuje wątku Connectivity
aplikacji.
Wywołaj ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
, gdy wywołanie zwrotne nie jest już istotne. Aplikacja może jednocześnie rejestrować wiele wywołań zwrotnych sieci.
Obiekt NetworkRequest
zawiera najczęściej używane funkcje, których potrzebuje większość aplikacji, w tym:
Podczas pisania aplikacji sprawdź wartości domyślne, aby zobaczyć, czy pasują do Twojego przypadku użycia, i wyczyść je, jeśli chcesz, aby aplikacja otrzymywała powiadomienia o sieciach, które nie mają tych możliwości. Z drugiej strony dodaj możliwości, aby uniknąć wywoływania w przypadku zmian łączności w sieciach, z którymi Twoja aplikacja nie wchodzi w interakcje.
Jeśli np. aplikacja musi wysyłać wiadomości MMS, dodaj
NET_CAPABILITY_MMS
do elementu NetworkRequest
, aby uniknąć otrzymywania informacji o wszystkich sieciach, które nie mogą wysyłać wiadomości MMS. Dodaj
TRANSPORT_WIFI_AWARE
jeśli Twoja aplikacja jest zainteresowana tylko łącznością Wi-Fi P2P.
NET_CAPABILITY_INTERNET
i NET_CAPABILITY_VALIDATED
przydadzą Ci się, jeśli chcesz mieć możliwość przesyłania danych za pomocą serwera
w internecie.
Przykładowa sekwencja wywołania zwrotnego
W tej sekcji opisujemy sekwencję wywołań zwrotnych, które aplikacja może otrzymać, jeśli zarejestruje zarówno domyślne, jak i zwykłe wywołanie zwrotne na urządzeniu z łącznością komórkową. W tym przykładzie urządzenie łączy się z dobrym punktem dostępu Wi-Fi, a następnie rozłącza się z nim. W przykładzie założono też, że na urządzeniu jest włączone ustawienie Mobilna transmisja danych zawsze aktywna.
Wygląda to tak:
Gdy aplikacja wywoła funkcję
registerNetworkCallback()
, natychmiast otrzyma wywołania zwrotne zonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
dla sieci komórkowej, ponieważ tylko ta sieć jest dostępna. Jeśli dostępna jest inna sieć, aplikacja otrzymuje też wywołania zwrotne dotyczące tej sieci.
Rysunek 1. Stan aplikacji po wywołaniu numeruregisterNetworkCallback()
.Następnie aplikacja wywołuje funkcję
registerDefaultNetworkCallback()
. Domyślny wywołanie zwrotne sieci zaczyna odbierać połączenia na numeryonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w przypadku sieci komórkowej, ponieważ jest ona siecią domyślną. Jeśli inna sieć, która nie jest domyślna, jest aktywna, aplikacja nie może odbierać połączeń w tej sieci.
Rysunek 2. Stan aplikacji po zarejestrowaniu sieci domyślnej.Później urządzenie łączy się z siecią Wi-Fi (bez limitu danych). Zwykłe wywołanie zwrotne sieci odbiera połączenia na numery
onAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w sieci Wi-Fi.
Rysunek 3. Stan aplikacji po połączeniu z siecią Wi-Fi bez limitu danych.W tym momencie weryfikacja sieci Wi-Fi może zająć trochę czasu. W tym przypadku wywołania
onNetworkCapabilitiesChanged()
w przypadku zwykłego wywołania zwrotnego sieci nie obejmują funkcjiNET_CAPABILITY_VALIDATED
. Po krótkim czasie otrzymuje połączenie zonNetworkCapabilitiesChanged()
, gdzie nowe możliwości obejmująNET_CAPABILITY_VALIDATED
. W większości przypadków weryfikacja przebiega bardzo szybko.Gdy sieć Wi-Fi zostanie zweryfikowana, system będzie ją preferować w stosunku do sieci komórkowej, głównie dlatego, że nie jest ona objęta limitem danych. Sieć Wi-Fi staje się siecią domyślną, więc wywołanie zwrotne sieci domyślnej otrzymuje wywołanie funkcji
onAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
dla sieci Wi-Fi. Sieć komórkowa przechodzi w tle, a zwykłe wywołanie zwrotne sieci odbiera połączenie na numeronLosing()
w sieci komórkowej.W tym przykładzie założono, że dane komórkowe są zawsze włączone na tym urządzeniu, więc sieć komórkowa nigdy nie jest odłączana. Jeśli to ustawienie jest wyłączone, po pewnym czasie sieć komórkowa rozłączy się, a zwykłe połączenie zwrotne otrzyma połączenie na numer
onLost()
.
Rysunek 4. Stan aplikacji po zweryfikowaniu sieci Wi-Fi.Później urządzenie nagle rozłącza się z Wi-Fi, ponieważ wychodzi poza zasięg. Po odłączeniu Wi-Fi zwykłe wywołanie zwrotne sieci odbiera połączenie z
onLost()
w przypadku Wi-Fi. Sieć komórkowa jest nową siecią domyślną, dlatego wywołanie zwrotne sieci domyślnej odbiera połączenia z numerówonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w sieci komórkowej.
Rysunek 5. Stan aplikacji po odłączeniu od sieci Wi-Fi.
Jeśli ustawienie Mobilna transmisja danych zawsze włączona jest wyłączone, po odłączeniu od Wi-Fi urządzenie próbuje ponownie połączyć się z siecią komórkową. Obraz jest podobny, ale z krótkim dodatkowym opóźnieniem w przypadku połączeń na numery onAvailable()
, a zwykłe połączenie zwrotne w sieci odbiera też połączenia na numery onAvailable()
, onNetworkCapabilitiesChanged()
i onLinkPropertiesChanged()
, ponieważ sieć komórkowa staje się dostępna.
Ograniczenia dotyczące korzystania z sieci do przesyłania danych
Możliwość wyświetlenia sieci z wywołaniem zwrotnym sieci nie oznacza, że aplikacja może używać tej sieci do przesyłania danych. Niektóre sieci nie zapewniają dostępu do internetu, a niektóre mogą być ograniczone do aplikacji z uprawnieniami. Aby sprawdzić połączenie z internetem, zapoznaj się z tymi artykułami:NET_CAPABILITY_INTERNET
i NET_CAPABILITY_VALIDATED
.
Korzystanie z sieci w tle również podlega sprawdzaniu uprawnień. Jeśli aplikacja ma korzystać z sieci w tle, potrzebuje uprawnienia CHANGE_NETWORK_STATE
.
Aplikacje z tymi uprawnieniami umożliwiają systemowi próbę uruchomienia sieci, która nie działa, np. sieci komórkowej, gdy urządzenie jest połączone z siecią Wi-Fi. Taka aplikacja wywołuje
ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback)
z NetworkCallback
, które ma być wywoływane po uruchomieniu sieci.