Android umożliwia aplikacjom poznawanie dynamicznych zmian w łączności. Aby śledzić zmiany w łączności i na nie reagować, użyj tych klas:
ConnectivityManagerinformuje aplikację o stanie łączności w systemie.- Klasa
Networkreprezentuje jedną z sieci, z którymi połączone jest urządzenie. Możesz użyć obiektuNetworkjako klucza do zbierania informacji o sieci za pomocąConnectivityManagerlub do wiązania gniazd w sieci. Gdy sieć zostanie rozłączona, obiektNetworkprzestanie być użyteczny. Nawet jeśli urządzenie później połączy się ponownie z tym samym urządzeniem, nowa sieć będzie reprezentowana przez nowy obiektNetwork. - Obiekt
LinkPropertieszawiera informacje o połączeniu z siecią, takie jak lista serwerów DNS , lokalne adresy IP i trasy sieciowe zainstalowane w sieci. - Obiekt
NetworkCapabilitieszawiera informacje o właściwościach sieci, takie jak transporty (Wi-Fi, sieć komórkowa, 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 płatna.
Aplikacje, które chcą znać bieżący stan łączności, mogą w dowolnym momencie wywołać metody ConnectivityManager, aby sprawdzić, jaki rodzaj sieci jest dostępny. Te metody są przydatne do debugowania i do okresowego sprawdzania stanu łączności dostępnego w danym momencie.
Synchroniczne metody ConnectivityManager nie informują jednak aplikacji o niczym, co dzieje się po wywołaniu, więc nie pozwalają na aktualizowanie interfejsu. Nie mogą też dostosowywać działania aplikacji na podstawie rozłą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ą zarejestrować wywołanie zwrotne w ConnectivityManager, aby otrzymywać powiadomienia o zmianach, które je interesują. Za pomocą wywołania zwrotnego aplikacja może natychmiast reagować na wszelkie istotne zmiany w łączności bez konieczności stosowania kosztownego sondowania, które może nie wykryć szybkich aktualizacji.
Korzystanie z NetworkCallback i innych sposobów sprawdzania stanu łączności urządzenia nie wymaga żadnych specjalnych uprawnień.
Niektóre sieci podlegają jednak określonym uprawnieniom.
Mogą na przykład istnieć sieci o ograniczonym dostępie, które nie są dostępne dla aplikacji. Powiązanie z siecią w tle wymaga uprawnienia CHANGE_NETWORK_STATE. Niektóre wywołania mogą też wymagać określonych uprawnień. Szczegółowe informacje znajdziesz w dokumentacji poszczególnych wywołań.
Uzyskiwanie natychmiastowego stanu
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();
Dzięki odniesieniu do sieci aplikacja może poprosić 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 korzystać z bardziej przydatnych funkcji, zarejestruj a
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, które system zna o sieci.
Obiekt LinkProperties zawiera informacje o trasach, adresach linków, nazwie interfejsu, informacjach o serwerze proxy (jeśli są dostępne) i serwerach DNS. Aby pobrać potrzebne informacje, wywołaj odpowiednią metodę w obiekcie LinkProperties.
Obiekt NetworkCapabilities zawiera informacje o transportach sieci i ich możliwościach.
Transport to abstrakcja medium fizycznego, przez które działa sieć. Typowe przykłady transportów to Ethernet, Wi-Fi i sieć komórkowa.
Sieci VPN i Wi-Fi typu peer-to-peer mogą być też transportami.
W Androidzie sieć może mieć jednocześnie wiele transportów. Przykładem jest sieć VPN działająca zarówno w sieciach Wi-Fi, jak i komórkowych. Sieć VPN ma transporty Wi-Fi, sieć komórkową 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 możliwości to MMS, NOT_METERED i INTERNET. Sieć z możliwością MMS może wysyłać i odbierać wiadomości MMS, a sieć bez tej możliwości nie może tego robić. Sieć z możliwością 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: wskazuje, że sieć jest skonfigurowana do dostępu do internetu. Dotyczy to konfiguracji, a nie rzeczywistej możliwości dotarcia do serwerów publicznych. Na przykład sieć może być skonfigurowana do dostępu do internetu, ale podlegać portalowi przechwytującemu.Sieć komórkowa operatora zwykle ma możliwość
INTERNET, a lokalna sieć Wi-Fi P2P zwykle jej nie ma. Aby sprawdzić rzeczywistą łączność, zobaczNET_CAPABILITY_VALIDATED.NET_CAPABILITY_NOT_METERED: wskazuje, że sieć nie jest płatna. Sieć jest klasyfikowana jako płatna, gdy użytkownik jest wrażliwy na duże zużycie danych w tym połączeniu ze względu na koszty, ograniczenia danych lub problemy 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. Sieć za portalem przechwytują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, chociaż zweryfikowana sieć może nadal podlegać filtrowaniu na podstawie adresu IP lub nagłym utratom łączności z powodu problemów takich jak słaby sygnał.NET_CAPABILITY_CAPTIVE_PORTAL: wskazuje, że sieć ma portal przechwytujący, gdy jest sondowana.
Istnieją inne możliwości, 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ę zmienić 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 będzie mogło uzyskać dostęp do publicznego internetu, a sieć zyska możliwość NET_CAPABILITY_VALIDATED i utraci możliwość NET_CAPABILITY_CAPTIVE_PORTAL.
Podobnie transporty sieci mogą się zmieniać dynamicznie.
Na przykład sieć VPN może się ponownie skonfigurować, aby używać szybszej sieci, która właśnie się pojawiła, np. przełączyć się z sieci komórkowej na Wi-Fi. W takim przypadku sieć traci transport TRANSPORT_CELLULAR i zyskuje transport TRANSPORT_WIFI, zachowując transport TRANSPORT_VPN.
Nasłuchiwanie zdarzeń sieciowych
Aby dowiedzieć się o zdarzeniach sieciowych, użyj klasy
NetworkCallback
razem z
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 pomiaru użycia danych od sieci płatnych oraz szybsze sieci od wolniejszych.
Gdy aplikacja wyśle żądanie sieciowe, np. za pomocą
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 podczas działania aplikacji. Typowym przykładem jest sytuacja, gdy urządzenie znajdzie się w zasięgu znanego, aktywnego, bez pomiaru i szybszego niż sieć komórkowa 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ę domyślną, każde nowe połączenie otwierane przez aplikację będzie korzystać z tej sieci. W pewnym momencie 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
onAvailable(Network)
dla nowej sieci. Zaimplementuj
onCapabilitiesChanged(Network,NetworkCapabilities),
onLinkPropertiesChanged(Network,LinkProperties),
lub obie te metody, aby odpowiednio reagować na zmiany w łączności.
W przypadku wywołania zwrotnego zarejestrowanego za pomocą registerDefaultNetworkCallback() metoda onLost() oznacza, że sieć utraciła status sieci domyślnej. Może zostać rozłączona.
Chociaż możesz dowiedzieć się o transportach używanych przez sieć domyślną, wysyłając zapytanie do
querying
NetworkCapabilities.hasTransport(int),
jest to słaby wskaźnik przepustowości lub płatności sieci. Aplikacja nie może zakładać, że Wi-Fi jest zawsze bez pomiaru i zawsze zapewnia lepszą przepustowość niż sieć komórkowa.
Zamiast tego użyj
NetworkCapabilities.getLinkDownstreamBandwidthKbps()
do pomiaru przepustowości oraz
NetworkCapabilites.hasCapability(int)
z
NET_CAPABILITY_NOT_METERED
argumentami, aby określić, czy sieć jest płatna. Więcej informacji znajdziesz w sekcji o
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 czasu, wywołaj je w osobnym wątku instancji roboczej za pomocą wariantu ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler).
Wyrejestruj wywołanie zwrotne, gdy nie będzie już potrzebne, wywołując
ConnectivityManager.unregisterNetworkCallback(NetworkCallback).
Dobrym miejscem na to jest 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ą istotną siecią dla większości aplikacji, niektóre aplikacje mogą być zainteresowane innymi dostępnymi sieciami. Aby się o nich dowiedzieć, aplikacje
tworzą NetworkRequest odpowiadający ich
potrzebom i wywołują
ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback).
Proces jest podobny do nasłuchiwania sieci domyślnej. Chociaż w danym momencie może istnieć tylko 1
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 rozłączona na stałe, a nie że nie jest już domyślna.
Aplikacja tworzy NetworkRequest, aby poinformować ConnectivityManager, jakiego rodzaju sieci chce nasłuchiwać. Ten przykład pokazuje, jak utworzyć NetworkRequest dla aplikacji, która jest zainteresowana tylko połączeniami internetowymi bez pomiaru użycia 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 bez pomiaru użycia danych w systemie.
Podobnie jak w przypadku wywołania zwrotnego sieci domyślnej, istnieje wersja
registerNetworkCallback(NetworkRequest, NetworkCallback, Handler)
, która akceptuje Handler, dzięki czemu nie obciąża wątku Connectivity aplikacji.
Gdy wywołanie zwrotne nie będzie już istotne, wywołaj
ConnectivityManager.unregisterNetworkCallback(NetworkCallback). Aplikacja może jednocześnie zarejestrować wiele wywołań zwrotnych sieci.
Dla wygody obiekt
NetworkRequest zawiera typowe możliwości, których potrzebuje większość aplikacji, w tym:
Podczas pisania aplikacji sprawdź ustawienia 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 każdej zmiany łączności w sieciach, z którymi aplikacja nie wchodzi w interakcje.
Jeśli na przykład aplikacja musi wysyłać wiadomości MMS, dodaj
NET_CAPABILITY_MMS
do NetworkRequest, aby nie otrzymywać informacji o wszystkich sieciach, które nie mogą
wysyłać wiadomości MMS. Dodaj
TRANSPORT_WIFI_AWARE
, jeśli aplikacja jest zainteresowana tylko łącznością Wi-Fi P2P.
NET_CAPABILITY_INTERNET i
NET_CAPABILITY_VALIDATED
są przydatne, jeśli chcesz przesyłać dane na serwer
w internenecie.
Przykładowa sekwencja wywołań zwrotnych
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 się od niego rozłącza. Przykład zakłada też, że na urządzeniu jest włączone ustawienie Mobilna transmisja danych zawsze włączona.
Oś czasu wygląda tak:
Gdy aplikacja wywoła
registerNetworkCallback(), wywołanie zwrotne natychmiast otrzyma wywołaniaonAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla sieci komórkowej, ponieważ tylko ta sieć jest dostępna. Jeśli dostępna jest inna sieć, aplikacja otrzyma też wywołania zwrotne dla tej sieci.
Rysunek 1. Stan aplikacji po wywołaniuregisterNetworkCallback().Następnie aplikacja wywołuje
registerDefaultNetworkCallback(). Wywołanie zwrotne sieci domyślnej zaczyna otrzymywać wywołaniaonAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla sieci komórkowej, ponieważ sieć komórkowa jest siecią domyślną. Jeśli inna sieć, która nie jest domyślna, jest aktywna, aplikacja nie może otrzymywać wywołań dla tej sieci.
Rysunek 2. Stan aplikacji po zarejestrowaniu sieci domyślnej.Później urządzenie łączy się z siecią Wi-Fi (bez pomiaru użycia danych). Zwykłe wywołanie zwrotne sieci otrzymuje wywołania
onAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla sieci Wi-Fi.
Rysunek 3. Stan aplikacji po połączeniu z siecią Wi-Fi bez pomiaru użycia danych.W tym momencie weryfikacja sieci Wi-Fi może potrwać. W takim przypadku wywołania
onNetworkCapabilitiesChanged()dla zwykłego wywołania zwrotnego sieci nie zawierają możliwościNET_CAPABILITY_VALIDATED. Po krótkim czasie otrzymuje wywołanieonNetworkCapabilitiesChanged(), w którym nowe możliwości obejmująNET_CAPABILITY_VALIDATED. W większości przypadków weryfikacja jest bardzo szybka.Gdy sieć Wi-Fi zostanie zweryfikowana, system preferuje ją od sieci komórkowej, głównie dlatego, że nie jest płatna. Sieć Wi-Fi staje się siecią domyślną, więc wywołanie zwrotne sieci domyślnej otrzymuje wywołania
onAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla sieci Wi-Fi. Sieć komórkowa przechodzi w tle, a zwykłe wywołanie zwrotne sieci otrzymuje wywołanieonLosing()dla sieci komórkowej.Ponieważ w tym przykładzie zakłada się, że mobilna transmisja danych jest zawsze włączona na tym urządzeniu, sieć komórkowa nigdy się nie rozłącza. Jeśli to ustawienie jest wyłączone, po pewnym czasie sieć komórkowa rozłączy się, a zwykłe wywołanie zwrotne sieci otrzyma wywołanie
onLost().
Rysunek 4. Stan aplikacji po zweryfikowaniu sieci Wi-Fi.Później urządzenie nagle rozłącza się z Wi-Fi, ponieważ wyszło poza zasięg. Ponieważ sieć Wi-Fi się rozłącza, zwykłe wywołanie zwrotne sieci otrzymuje wywołanie
onLost()dla Wi-Fi. Ponieważ sieć komórkowa jest nową siecią domyślną, wywołanie zwrotne sieci domyślnej otrzymuje wywołaniaonAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla sieci komórkowej.
Rysunek 5. Stan aplikacji po rozłączeniu z siecią Wi-Fi.
Jeśli ustawienie Mobilna transmisja danych zawsze włączona jest wyłączone, po rozłączeniu 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 wywołań onAvailable(), a zwykłe wywołanie zwrotne sieci otrzymuje też wywołania 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 za pomocą wywołania zwrotnego sieci nie oznacza, że aplikacja może używać tej sieci do przesyłania danych. Niektóre sieci nie zapewniają łączności z internetem, a niektóre mogą być ograniczone do aplikacji z uprawnieniami. Aby sprawdzić łączność z internetem, zobacz
NET_CAPABILITY_INTERNET
i
NET_CAPABILITY_VALIDATED.
Korzystanie z sieci w tle podlega też sprawdzaniu uprawnień. Jeśli aplikacja
chce korzystać z sieci w tle, potrzebuje
CHANGE_NETWORK_STATE
uprawnienia.
Aplikacje z tym uprawnieniem umożliwiają systemowi próbę uruchomienia sieci, która nie jest aktywna, 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.