Android umożliwia aplikacjom zapamiętywanie informacji o dynamicznych zmianach w łączności. Użyj poniższych klas, aby śledzić zmiany połączeń i reagować na nie:
ConnectivityManager
informuje aplikację o stanie połączenia w systemie.- Klasa
Network
reprezentuje jedną z sieci, z którą połączone jest urządzenie. ObiektuNetwork
możesz użyć jako klucza do zbierania informacji o sieci za pomocąConnectivityManager
lub do wiązania gniazd w sieci. Po rozłączeniu sieci obiektNetwork
przestanie być użyteczny. Nawet jeśli urządzenie później ponownie połączy się z tym samym urządzeniem, nowy obiektNetwork
reprezentuje nową sieć. - Obiekt
LinkProperties
zawiera informacje o połączeniu z siecią, takie jak lista serwerów DNS, lokalne adresy IP i trasy sieciowe zainstalowane w sieci. - Obiekt
NetworkCapabilities
zawiera informacje o właściwościach sieci, np. o środkach transportu (Wi-Fi, komórkowe lub Bluetooth) oraz o możliwościach sieci. Możesz na przykład wysłać zapytanie do obiektu, aby sprawdzić, czy sieć może wysyłać MMS-y, czy znajduje się za portalem przechwytującym, czy jest objęta pomiarem.
Aplikacje, które w dowolnym momencie chcą mieć natychmiastowy stan połączenia, mogą wywoływać metody ConnectivityManager
, aby dowiedzieć się, jaki rodzaj sieci jest dostępny. Metody te są pomocne przy debugowaniu i od czasu do czasu sprawdzaj podsumowanie połączenia, które jest dostępne w danym momencie.
Jednak synchroniczne metody ConnectivityManager
nie informują aplikacji o tym, co dzieje się po wywołaniu, więc nie pozwalają na aktualizację interfejsu użytkownika. Nie mogą też dostosować działania aplikacji na podstawie rozłączenia sieci ani zmian możliwości sieci.
Łączność może się zmienić w każdej chwili, a większość aplikacji musi mieć zawsze aktualny wgląd w stan sieci na urządzeniu. Aplikacje mogą zarejestrować wywołanie zwrotne przy użyciu funkcji ConnectivityManager
, aby otrzymywać alerty o zmianach, które są dla nich ważne. Dzięki wywołaniu zwrotnemu aplikacja może natychmiast zareagować na każdą istotną zmianę połączenia bez konieczności uciekania się do kosztownych ankiet, które mogłyby przeoczyć szybkie aktualizacje.
Korzystanie z NetworkCallback
i innych sposobów sprawdzania stanu połączenia urządzenia nie wymaga żadnych uprawnień.
Niektóre sieci wymagają jednak określonych uprawnień.
Mogą na przykład istnieć sieci z ograniczonym dostępem, które nie są dostępne dla aplikacji. Powiązanie z siecią w tle wymaga uprawnienia CHANGE_NETWORK_STATE
. Niektóre wywołania mogą wymagać określonych uprawnień do uruchomienia. Szczegółowe informacje znajdziesz w dokumentacji konkretnego wywołania.
Uzyskaj natychmiastowy stan
Urządzenie z Androidem może obsługiwać wiele połączeń jednocześnie.
Aby uzyskać informacje o bieżącym stanie sieci, najpierw pobierz instancję ConnectivityManager
:
Kotlin
val connectivityManager = getSystemService(ConnectivityManager::class.java)
Java
ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);
Następnie użyj tej instancji, by uzyskać odniesienie do bieżącej domyślnej sieci aplikacji:
Kotlin
val currentNetwork = connectivityManager.getActiveNetwork()
Java
Network currentNetwork = connectivityManager.getActiveNetwork();
Dzięki odniesienia do sieci aplikacja może prosić o informacje na jej temat:
Kotlin
val caps = connectivityManager.getNetworkCapabilities(currentNetwork) val linkProperties = connectivityManager.getLinkProperties(currentNetwork)
Java
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(currentNetwork); LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);
Aby mieć dostęp do bardziej przydatnych funkcji, zarejestruj NetworkCallback
.
Więcej informacji o rejestrowaniu wywołań zwrotnych sieci znajdziesz w artykule o nasłuchiwaniu zdarzeń sieciowych.
Funkcjonalność sieci i właściwości linku
Obiekty NetworkCapabilities
i LinkProperties
dostarczają informacji o wszystkich atrybutach sieci, które system wie.
Obiekt LinkProperties
zna trasy, adresy linków, nazwę interfejsu, informacje o serwerach proxy (jeśli są dostępne) i serwerach DNS. Wywołaj odpowiednią metodę w obiekcie LinkProperties
, aby pobrać potrzebne informacje.
Obiekt NetworkCapabilities
zawiera informacje o transportach sieci i ich możliwościach.
Transport to abstrakcja nośnika fizycznego, przez który działa sieć. Typowe przykłady sieci transportu to Ethernet, Wi-Fi i sieć komórkowa.
Mogą to być również sieci VPN oraz sieci Wi-Fi typu peer-to-peer.
Na Androidzie sieć może mieć wiele transportów jednocześnie. Przykładem może być sieć VPN działająca zarówno przez Wi-Fi, jak i sieci komórkowe. Sieć VPN obejmuje sieć Wi-Fi,
mobilną i VPN. Aby dowiedzieć się, czy sieć ma określony środek transportu, użyj metody NetworkCapabilities.hasTransport(int)
z jedną ze stałych NetworkCapabilities.TRANSPORT_*
.
Możliwość opisuje właściwość sieci. Przykładowe możliwości to MMS
, NOT_METERED
i INTERNET
. Sieć obsługująca MMS-y może wysyłać i odbierać wiadomości przy użyciu usługi przesyłania wiadomości multimedialnych, natomiast sieć bez tej funkcji nie będzie mieć takiej możliwości. Sieć obsługująca funkcję NOT_METERED
nie nalicza opłat za przesyłanie danych. Aplikacja może sprawdzić odpowiednie możliwości, używając metody NetworkCapabilities.hasCapability(int)
z jedną ze stałych NetworkCapabilities.NET_CAPABILITY_*
.
Najbardziej przydatne stałe NET_CAPABILITY_*
to:
NET_CAPABILITY_INTERNET
: wskazuje, że sieć jest skonfigurowana pod kątem dostępu do internetu. Chodzi o konfigurację, a nie o rzeczywistą możliwość dostępu do serwerów publicznych. Na przykład można skonfigurować sieć tak, aby łączyć się z internetem, ale podlegać portalu przechwytującego.Sieć komórkowa operatora zwykle ma funkcję
INTERNET
, a lokalna sieć P2P – Wi-Fi – nie. Informacje o rzeczywistych połączeniach znajdziesz naNET_CAPABILITY_VALIDATED
.NET_CAPABILITY_NOT_METERED
: wskazuje, że sieć nie ma pomiaru wykorzystania limitu. Sieć jest klasyfikowana jako z pomiarem użycia danych, gdy użytkownik wykazuje tendencję do wysokiego poziomu wykorzystania danych przez to połączenie z powodu kosztów finansowych, ograniczeń w danych lub problemów z wydajnością baterii.NET_CAPABILITY_NOT_VPN
: wskazuje, że sieć nie jest wirtualną siecią prywatną.NET_CAPABILITY_VALIDATED
: wskazuje, że sieć zapewnia rzeczywisty dostęp do publicznego internetu, gdy jest sondowana. Tej funkcji nie ma w sieciach portalu przechwytującego ani w sieci, która nie obsługuje rozpoznawania nazw domen. Jest to najbliższa wartość, jaką system może wywnioskować na temat sieci rzeczywiście zapewniającej dostęp, chociaż zweryfikowana sieć może w zasadzie podlegać filtrowaniu na podstawie adresu IP lub może dochodzić do nagłej utraty połączenia z powodu problemów takich jak słaby sygnał.NET_CAPABILITY_CAPTIVE_PORTAL
: wskazuje, że sieć ma portal przechwytujący, gdy jest sprawdzany.
Istnieją też inne możliwości, którymi mogą być zainteresowane bardziej specjalistyczne aplikacje.
Więcej informacji znajdziesz w definicjach parametrów w artykule NetworkCapabilities.hasCapability(int)
.
Możliwości sieci mogą się zmienić w każdej chwili. Gdy system wykryje portal przechwytujący, wyświetli powiadomienie z prośbą o zalogowanie. W trakcie tego działania sieć ma możliwości NET_CAPABILITY_INTERNET
i NET_CAPABILITY_CAPTIVE_PORTAL
, ale nie 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ć uzyska obsługę NET_CAPABILITY_VALIDATED
i utraci możliwość NET_CAPABILITY_CAPTIVE_PORTAL
.
Transport w sieci również może się dynamicznie zmieniać.
Na przykład sieć VPN może się zmienić w taki sposób, aby korzystała z szybszej sieci, która właśnie powstała. Może na przykład przełączyć się z mobilnej na Wi-Fi w swojej sieci podstawowej. W tym przypadku sieć traci transport publiczny TRANSPORT_CELLULAR
i zyskuje transport TRANSPORT_WIFI
, zachowując jednocześnie transport TRANSPORT_VPN
.
Nasłuchuj zdarzeń sieciowych
Aby uzyskać informacje o zdarzeniach sieciowych, użyj klasy NetworkCallback
razem z ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback)
i ConnectivityManager.registerNetworkCallback(NetworkCallback)
. Te dwie metody służą
różnym celom.
Wszystkie aplikacje na Androida mają sieć domyślną, która jest określana przez system. System zazwyczaj preferuje sieci bez pomiaru sieci z pomiarem użycia danych, a szybsze sieci od wolniejszych.
Gdy aplikacja wyśle żądanie sieciowe, na przykład za pomocą HttpsURLConnection
, system może spełnić to żądanie z użyciem sieci domyślnej. Aplikacje mogą wysyłać
ruch również w innych sieciach. Więcej informacji znajdziesz w sekcji o dodatkowych sieciach.
Sieć ustawiona jako sieć domyślna może się zmienić w dowolnym momencie podczas działania aplikacji. Typowym przykładem jest urządzenie znajdujące się w zasięgu znanego, aktywnego, niepomiarowego i szybszego niż komórkowy punktu dostępu Wi-Fi. Urządzenie łączy się z tym punktem dostępu i przełącza domyślną sieć dla wszystkich aplikacji na nową sieć Wi-Fi.
Gdy nowa sieć stanie się siecią domyślną, każde nowe połączenie otwierane przez aplikację będzie używać tej sieci. W pewnym momencie wszystkie pozostałe połączenia w poprzedniej domyślnej sieci zostaną wymuszone. Jeśli aplikacja ma wiedzieć o zmianie sieci domyślnej, rejestruje takie wywołanie zwrotne sieci:
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ę siecią domyślną, aplikacja otrzyma w jej przypadku wywołanie onAvailable(Network)
. Aby odpowiednio reagować na zmiany w łączności, zaimplementuj onCapabilitiesChanged(Network,NetworkCapabilities)
, onLinkPropertiesChanged(Network,LinkProperties)
lub oba te elementy.
W przypadku wywołania zwrotnego zarejestrowanego za pomocą registerDefaultNetworkCallback()
onLost()
oznacza, że sieć utraciła status sieci domyślnej. Może być odłączone.
Chociaż można dowiedzieć się więcej o transmisjach używanych w sieci domyślnej, wysyłając zapytania do NetworkCapabilities.hasTransport(int)
, nie jest to serwer proxy o słabych parametrach związanych z przepustowością lub pomiarem wykorzystania sieci. Aplikacja nie może zakładać, że sieć Wi-Fi zawsze jest bez pomiaru i ma większą przepustowość niż sieć komórkowa.
Zamiast tego użyj NetworkCapabilities.getLinkDownstreamBandwidthKbps()
do pomiaru przepustowości, a NetworkCapabilites.hasCapability(int)
z argumentami NET_CAPABILITY_NOT_METERED
do określenia pomiaru wykorzystania. Więcej informacji znajdziesz w sekcji o funkcjach sieci i właściwościach linków.
Domyślnie metody wywołania zwrotnego są wywoływane w wątku połączenia aplikacji, który jest oddzielnym wątkiem używanym przez funkcję ConnectivityManager
. Jeśli implementacja wywołań zwrotnych musi dłużej działać, wywołaj je w osobnym wątku instancji roboczej, używając wariantu ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler)
.
Wyrejestruj oddzwonienie, gdy nie jest już używane, pod numerem ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
.
Możesz to zrobić w onPause()
głównej aktywności, zwłaszcza jeśli rejestrujesz wywołanie zwrotne w onResume()
.
Dodatkowe sieci
Mimo że sieć domyślna to jedyna sieć w przypadku większości aplikacji, niektóre aplikacje mogą być zainteresowane innymi dostępnymi sieciami. Aby się o tym dowiedzieć, aplikacje tworzą NetworkRequest
pasujące do ich potrzeb i wywołują ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback)
.
Ten proces przypomina nasłuchiwanie
sieci domyślnej. Mimo że w danym momencie może istnieć tylko jedna sieć domyślna, która obowiązuje w przypadku aplikacji, ta wersja pozwala aplikacji zobaczyć wszystkie dostępne sieci jednocześnie. wywołanie onLost(Network)
oznacza więc, że sieć została odłączona na stałe, ale nie jest to już sieć domyślna.
Aplikacja tworzy NetworkRequest
, który informuje ConnectivityManager
o rodzaju sieci, których chce słuchać. Poniższy przykład pokazuje, jak utworzyć NetworkRequest
dla aplikacji zainteresowanej tylko połączeniami z internetem bez pomiaru:
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 sieci w systemie bez pomiaru.
Jeśli chodzi o domyślne wywołanie zwrotne sieci, istnieje wersja registerNetworkCallback(NetworkRequest, NetworkCallback, Handler)
, która akceptuje Handler
, więc nie wczytuje wątku Connectivity
Twojej aplikacji.
Wywołaj ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
, gdy wywołanie zwrotne nie będzie już aktualne. Aplikacja może jednocześnie rejestrować
wiele wywołań zwrotnych sieci.
Dla wygody obiekt NetworkRequest
zawiera typowe funkcje, których potrzebuje większość aplikacji, w tym:
Pisząc aplikację, sprawdź wartości domyślne, aby zobaczyć, czy pasują do Twojego przypadku użycia, i wyczyść je, jeśli chcesz, by aplikacja była powiadamiana o sieciach, które nie mają tych funkcji. Z drugiej strony dodaj funkcje, aby uniknąć wywołania w przypadku zmiany połączenia w sieciach, z którymi Twoja aplikacja nie wchodzi w interakcję.
Jeśli na przykład Twoja aplikacja musi wysyłać MMS-y, dodaj NET_CAPABILITY_MMS
do NetworkRequest
, aby otrzymywać informacje o wszystkich sieciach, które nie mogą wysyłać MMS-ów. Dodaj TRANSPORT_WIFI_AWARE
, jeśli Twoja aplikacja potrzebuje tylko połączeń P2P z siecią Wi-Fi.
NET_CAPABILITY_INTERNET
i NET_CAPABILITY_VALIDATED
są przydatne, jeśli interesuje Cię możliwość przenoszenia danych z serwerem w internecie.
Przykładowa sekwencja wywołania zwrotnego
W tej sekcji opisujemy sekwencję wywołań zwrotnych, które może otrzymać aplikacja, jeśli zarejestruje zarówno domyślne wywołanie zwrotne, jak i zwykłe wywołanie zwrotne na urządzeniu z łącznością komórkową. W tym przykładzie urządzenie łączy się z punktem dostępu Wi-Fi, a potem się od niego rozłącza. W tym przykładzie zakładamy też, że urządzenie ma włączoną opcję Mobilna transmisja danych zawsze włączona.
Harmonogram wygląda tak:
Gdy aplikacja wywoła
registerNetworkCallback()
, wywołanie zwrotne natychmiast otrzyma połączenia z sieci komórkowejonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
, ponieważ dostępna jest tylko ta sieć. Jeśli dostępna jest inna sieć, aplikacja odbiera też wywołania zwrotne do tej sieci.
Rysunek 1. Stan aplikacji po wywołaniu aplikacjiregisterNetworkCallback()
.Następnie aplikacja wywołuje metodę
registerDefaultNetworkCallback()
. Domyślne wywołanie zwrotne sieci zacznie odbierać połączenia z numeramionAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w przypadku sieci komórkowej, ponieważ domyślną siecią jest sieć komórkowa. Jeśli działa inna sieć inna niż domyślna, aplikacja nie będzie mogła odbierać połączeń z tej sieci.
Rysunek 2. Stan aplikacji po zarejestrowaniu sieci domyślnej.Następnie urządzenie łączy się z siecią Wi-Fi (bez pomiaru). Zwykłe wywołanie zwrotne sieci odbiera połączenia z numerami
onAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w przypadku sieci Wi-Fi.
Rysunek 3. Stan aplikacji po połączeniu się z siecią Wi-Fi bez pomiaru.W tym momencie może minąć trochę czasu, zanim sieć Wi-Fi zweryfikuje się. W tym przypadku wywołanie zwrotne
onNetworkCapabilitiesChanged()
w standardowej sieci nie zawiera funkcjiNET_CAPABILITY_VALIDATED
. Po krótkim czasie otrzymuje wywołanieonNetworkCapabilitiesChanged()
, gdzie do nowych funkcji należąNET_CAPABILITY_VALIDATED
. W większości przypadków weryfikacja trwa bardzo krótko.Po sprawdzeniu sieci Wi-Fi system preferuje ją od sieci komórkowej, głównie dlatego, że nie jest mierzona. Sieć Wi-Fi staje się siecią domyślną, więc domyślne wywołanie zwrotne sieci Wi-Fi otrzymuje wywołania
onAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
. Sieć komórkowa przechodzi w tle, a standardowe wywołanie zwrotne sieci komórkowej otrzymuje wywołanieonLosing()
.W tym przykładzie zakładamy, że mobilna transmisja danych na tym urządzeniu jest zawsze włączona, więc sieć komórkowa nigdy się nie rozłącza. Jeśli to ustawienie jest wyłączone, po pewnym czasie sieć komórkowa zostanie rozłączona i zwykłe wywołanie zwrotne sieci otrzyma wywołanie
onLost()
.
Rysunek 4. Stan aplikacji po zweryfikowaniu sieci Wi-Fi.Po jakimś czasie urządzenie nagle rozłącza się z Wi-Fi, ponieważ jest poza zasięgiem. Wi-Fi się rozłącza, więc zwykłe wywołanie zwrotne sieci przez Wi-Fi otrzyma na adres
onLost()
. Komórka to nowa sieć domyślna, dlatego domyślne wywołanie zwrotne sieci komórkowej otrzymuje wywołaniaonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
dla sieci komórkowej.
Rysunek 5. Stan aplikacji po odłączeniu od sieci Wi-Fi.
Jeśli ustawienie Mobilna transmisja danych jest zawsze włączone, po rozłączeniu Wi-Fi urządzenie spróbuje ponownie połączyć się z siecią komórkową. Obraz jest podobny, ale z niewielkim dodatkowym opóźnieniem w przypadku wywołań onAvailable()
, a standardowe wywołanie zwrotne sieci otrzymuje też wywołania onAvailable()
, onNetworkCapabilitiesChanged()
i onLinkPropertiesChanged()
, ponieważ dostępne są też urządzenia mobilne.
Ograniczenia dotyczące korzystania z sieci do przesyłania danych
To, że widzisz sieć z wywołaniem zwrotnym, nie oznacza, że aplikacja może używać tej sieci do przesyłania danych. Niektóre sieci nie zapewniają połączenia z internetem, a inne mogą być dostępne tylko dla aplikacji z podwyższonymi uprawnieniami. Aby sprawdzić połączenie z internetem, zapoznaj się z instrukcjami NET_CAPABILITY_INTERNET
i NET_CAPABILITY_VALIDATED
.
Korzystanie z sieci działających w tle podlega również sprawdzaniu uprawnień. Jeśli Twoja aplikacja chce korzystać z sieci w tle, musi mieć uprawnienie CHANGE_NETWORK_STATE
.
Aplikacje z tymi uprawnieniami pozwalają systemowi
próbować wyświetlić sieć, która nie działa, np. sieć komórkową, gdy urządzenie jest połączone z siecią Wi-Fi. Taka aplikacja wywołuje ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback)
z elementem NetworkCallback
, który zostaje wywołany po wywołaniu sieci.