Android umożliwia aplikacjom uzyskiwanie informacji o dynamicznych zmianach w łączności. Aby śledzić zmiany połączenia i na nie reagować, użyj tych klas:
ConnectivityManagerinformuje aplikację o stanie połączenia w systemie.- Klasa
Networkreprezentuje jedną z sieci, z którymi jest połączone urządzenie. Możesz użyć obiektuNetworkjako klucza do zbierania informacji o sieci za pomocąConnectivityManagerlub do powiązania gniazd w sieci. Gdy sieć zostanie odłączona, obiektNetworkprzestanie być użyteczny. Nawet jeśli urządzenie później ponownie połączy się z tym samym urządzeniem, nową sieć będzie reprezentować nowy obiektNetwork. - Obiekt
LinkPropertieszawiera informacje o połączeniu sieciowym, takie jak lista serwerów DNS, lokalne adresy IP i trasy sieciowe zainstalowane dla sieci. - Obiekt
NetworkCapabilitieszawiera informacje o właściwościach sieci, takich jak transport (Wi-Fi, sieć komórkowa, Bluetooth) i możliwości sieci. Możesz na przykład wysłać zapytanie do obiektu, aby określić, czy sieć może wysyłać MMS-y, czy jest za portalem przechwytującym lub czy jest mierzona.
Aplikacje, które potrzebują informacji o stanie połączenia w danym momencie, mogą wywoływać metody ConnectivityManager, aby dowiedzieć się, jaki rodzaj sieci jest dostępny. Te metody są przydatne do debugowania i okresowego sprawdzania stanu połączenia w danym momencie.
Jednak metody synchroniczne ConnectivityManager nie informują aplikacji o tym, 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.
Połączenie może się zmienić w każdej chwili, a większość aplikacji musi mieć zawsze aktualny widok stanu sieci na urządzeniu. Aplikacje mogą zarejestrować wywołanie zwrotne za pomocą ConnectivityManager, aby otrzymywać powiadomienia o zmianach, które są dla nich istotne. Dzięki wywołaniu zwrotnemu aplikacja może natychmiast reagować na każdą istotną zmianę w połączeniu bez konieczności przeprowadzania kosztownego sondowania, które może nie uwzględniać szybkich aktualizacji.
Używanie NetworkCallback i innych sposobów sprawdzania stanu połączenia urządzenia nie wymaga żadnych specjalnych 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. Wiązanie z siecią działającą w tle wymaga uprawnienia CHANGE_NETWORK_STATE. Niektóre wywołania mogą wymagać określonych uprawnień. Szczegółowe informacje znajdziesz w dokumentacji dotyczącej poszczególnych wywołań.
Pobierz stan chwilowy
Urządzenie z Androidem może utrzymywać 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, aby uzyskać odniesienie do bieżącej sieci domyślnej aplikacji:
Kotlin
val currentNetwork = connectivityManager.getActiveNetwork()
Java
Network currentNetwork = connectivityManager.getActiveNetwork();
Dzięki odwołaniu do sieci aplikacja może poprosić o informacje o niej:
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 bardziej 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 dostarczają informacji o wszystkich atrybutach, które system zna na temat sieci.
Obiekt LinkProperties zawiera informacje o trasach, adresach linków, nazwie interfejsu, serwerach proxy (jeśli są) i serwerach DNS. Wywołaj odpowiednią metodę w obiekcie LinkProperties, aby pobrać potrzebne informacje.
Obiekt NetworkCapabilities zawiera informacje o transporcie sieciowym i możliwościach sieci.
Transport to abstrakcja fizycznego medium, w którym działa sieć. Typowe przykłady transportu 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 jest sieć VPN działająca zarówno w sieciach Wi-Fi, jak i sieciach komórkowych. Sieć VPN ma transporty Wi-Fi, komórkowy i VPN. Aby dowiedzieć się, 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ładowe funkcje to MMS, NOT_METERED i INTERNET. Sieć z obsługą MMS-ów może wysyłać i odbierać wiadomości multimedialne, a sieć bez tej funkcji nie może tego robić. Sieć z funkcją NOT_METERED nie obciąża użytkownika opłatami za dane. Aplikacja może sprawdzić odpowiednie funkcje, 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 tak, aby umożliwiać dostęp do internetu. Dotyczy to konfiguracji, a nie rzeczywistej możliwości uzyskania dostępu do serwerów publicznych. Sieć może być na przykład skonfigurowana tak, aby umożliwiać dostęp do internetu, ale podlegać portalowi przechwytującemu.Sieć komórkowa operatora zwykle obsługuje funkcję
INTERNET, podczas gdy lokalna sieć Wi-Fi P2P zwykle jej nie obsługuje. Informacje o rzeczywistej łączności znajdziesz na stronieNET_CAPABILITY_VALIDATED.NET_CAPABILITY_NOT_METERED: wskazuje, że sieć nie jest mierzona. Sieć jest klasyfikowana jako taryfowa, gdy użytkownik jest wrażliwy na duże wykorzystanie danych w tym połączeniu ze względu na koszty, limity 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 podczas sprawdzania. Sieć za portalem przechwytującym lub sieć, która nie zapewnia tłumaczenia nazwy domeny, nie ma tej funkcji. To najbliższa sieć, którą system może wskazać jako faktycznie zapewniającą dostęp, chociaż zweryfikowana sieć może nadal podlegać filtrowaniu na podstawie adresu IP lub nagle utracić połączenie z powodu problemów, takich jak słaby sygnał.NET_CAPABILITY_CAPTIVE_PORTAL: wskazuje, że sieć ma portal przechwytujący, gdy jest sprawdzana.
Istnieją inne funkcje, które mogą być interesujące dla bardziej wyspecjalizowanych aplikacji.
Więcej informacji znajdziesz w definicjach parametrów w NetworkCapabilities.hasCapability(int).
Możliwości sieci mogą się zmienić w każdej chwili. Gdy system wykryje portal przechwytujący, wyświetla powiadomienie z prośbą o zalogowanie się. W tym czasie sieć ma funkcje NET_CAPABILITY_INTERNET i NET_CAPABILITY_CAPTIVE_PORTAL, ale nie ma funkcji 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 funkcję NET_CAPABILITY_VALIDATED i utraci funkcję NET_CAPABILITY_CAPTIVE_PORTAL.
Podobnie transporty sieci mogą się zmieniać dynamicznie.
Na przykład sieć VPN może zmienić konfigurację, aby korzystać z szybszej sieci, która właśnie się pojawiła, np. przełączyć się z sieci komórkowej na Wi-Fi. W tym przypadku sieć traci transport TRANSPORT_CELLULAR i 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 razem z ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback) i ConnectivityManager.registerNetworkCallback(NetworkCallback). Te 2 metody służą różnym celom.
Wszystkie aplikacje na Androida mają sieć domyślną, która jest określana przez system. System zwykle preferuje sieci bez pomiaru transmisji danych i szybsze sieci.
Gdy aplikacja wysyła żądanie sieciowe, np. za pomocą HttpsURLConnection, system realizuje je przy użyciu sieci domyślnej. Aplikacje mogą też wysyłać ruch
w innych sieciach. Więcej informacji znajdziesz w sekcji o sieciach dodatkowych.
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 połączy się z tym punktem dostępu i przełączy 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ą przymusowo zakończone. Jeśli dla aplikacji ważne jest, aby wiedzieć, kiedy zmienia się sieć domyślna, rejestruje ona 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 połączeniu.
W przypadku wywołania zwrotnego zarejestrowanego za pomocą registerDefaultNetworkCallback() onLost() oznacza, że sieć utraciła stan sieci domyślnej. Może być odłączony.
Chociaż możesz dowiedzieć się, z jakich transportów korzysta sieć domyślna, wysyłając zapytanie do NetworkCapabilities.hasTransport(int), nie jest to dobry sposób na określenie przepustowości ani taryfikacji sieci. Aplikacja nie może zakładać, że Wi-Fi jest zawsze bezpłatne i zawsze zapewnia lepszą przepustowość niż sieć komórkowa.
Zamiast tego użyj NetworkCapabilities.getLinkDownstreamBandwidthKbps() do pomiaru przepustowości oraz NetworkCapabilites.hasCapability(int) z argumentami NET_CAPABILITY_NOT_METERED do określenia, czy połączenie jest taryfowe. Więcej informacji znajdziesz w sekcji dotyczącej NetworkCapabilities i LinkProperties.
Domyślnie metody wywołania zwrotnego są wywoływane w wątku połączenia aplikacji, który jest osobnym 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, używając wariantu ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler).
Jeśli nie potrzebujesz już wywołania zwrotnego, wyrejestruj je, wywołując funkcję 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ą odpowiednią siecią dla 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 odpowiadający ich potrzebom i zadzwoń pod numer ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback).
Proces jest podobny do nasłuchiwania sieci domyślnej. Chociaż w danym momencie może być tylko jedna domyślna sieć, ta wersja umożliwia aplikacji jednoczesne wyświetlanie wszystkich dostępnych sieci, więc wywołanie onLost(Network) oznacza, że sieć została odłączona na stałe, a nie, że nie jest już domyślna.
Aplikacja tworzy obiekt NetworkRequest, aby poinformować obiekt ConnectivityManager, jakich sieci chce nasłuchiwać. Poniższy przykład pokazuje, jak utworzyć obiekt NetworkRequest dla aplikacji, która jest zainteresowana tylko połączeniami internetowymi bez taryf:
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 otrzymuje informacje o wszystkich zmianach dotyczących dowolnej sieci bez pomiaru transmisji danych w systemie.
Jeśli chodzi o domyślne wywołanie zwrotne sieci, 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ż potrzebne. Aplikacja może jednocześnie zarejestrować wiele wywołań zwrotnych sieci.
Dla wygody obiekt NetworkRequest zawiera typowe funkcje, których potrzebuje większość aplikacji, w tym:
Podczas pisania aplikacji sprawdź, czy wartości domyślne pasują do Twojego przypadku użycia, i wyczyść je, jeśli chcesz, aby aplikacja była powiadamiana o sieciach, które nie mają tych funkcji. Z drugiej strony dodaj funkcje, aby uniknąć wywoływania w przypadku jakichkolwiek zmian połączenia 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. Jeśli aplikacja wymaga tylko połączenia Wi-Fi P2P, dodaj TRANSPORT_WIFI_AWARE.
NET_CAPABILITY_INTERNET i NET_CAPABILITY_VALIDATED są przydatne, jeśli chcesz przesyłać dane na serwer w internecie.
Przykładowa sekwencja wywołania zwrotnego
W tej sekcji opisano 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 odłącza. W przykładzie założono też, że na urządzeniu jest włączone ustawienie Mobilna transmisja danych zawsze włączona.
Harmonogram wygląda tak:
Gdy aplikacja wywołuje metodę
registerNetworkCallback(), wywołanie zwrotne natychmiast otrzymuje wywołania metodonAvailable(),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 dla tej sieci.
Rysunek 1. Stan aplikacji po wywołaniu metodyregisterNetworkCallback().Następnie aplikacja wywołuje metodę
registerDefaultNetworkCallback(). Domyślne wywołanie zwrotne sieci zaczyna odbierać wywołania doonAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla sieci komórkowej, ponieważ jest ona siecią domyślną. Jeśli działa inna, niedomyślna sieć, 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 pomiaru). Zwykłe wywołanie zwrotne sieci odbiera wywołania
onAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla sieci Wi-Fi.
Rysunek 3. Stan aplikacji po połączeniu z siecią Wi-Fi bez pomiaru.W tym momencie weryfikacja sieci Wi-Fi może chwilę potrwać. W takim przypadku wywołania
onNetworkCapabilitiesChanged()dla zwykłego wywołania zwrotnego sieci nie obejmują funkcjiNET_CAPABILITY_VALIDATED. Po krótkim czasie otrzymuje połączenie z numeremonNetworkCapabilitiesChanged(), gdzie nowe funkcje obejmująNET_CAPABILITY_VALIDATED. W większości przypadków weryfikacja przebiega bardzo szybko.Gdy sieć Wi-Fi zostanie zweryfikowana, system będzie preferował ją zamiast sieci komórkowej, głównie dlatego, że nie jest ona mierzona. Sieć Wi-Fi staje się siecią domyślną, więc wywołanie zwrotne sieci domyślnej otrzymuje wywołanie
onAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla sieci Wi-Fi. Sieć komórkowa przechodzi do tła, a regularne wywołanie zwrotne sieci otrzymuje wywołanieonLosing()dla sieci komórkowej.W tym przykładzie zakładamy, że mobilna transmisja danych jest zawsze włączona na tym urządzeniu, więc sieć komórkowa nigdy się nie rozłącza. Jeśli ustawienie jest wyłączone, po pewnym czasie sieć komórkowa się rozłącza, a zwykłe wywołanie zwrotne sieci otrzymuje wywołanie
onLost().
Rysunek 4. Stan aplikacji po zweryfikowaniu sieci Wi-Fi.Później urządzenie nagle rozłącza się z Wi-Fi, ponieważ straciło zasięg. Z powodu rozłączenia Wi-Fi 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 odbiera wywołania metodonAvailable(),onNetworkCapabilitiesChanged()ionLinkPropertiesChanged()dla 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 rozłączeniu Wi-Fi urządzenie próbuje ponownie połączyć się z siecią komórkową. Sytuacja jest podobna, ale występuje krótkie dodatkowe opóźnienie w przypadku wywołań onAvailable(), a standardowe wywołanie zwrotne sieci odbiera 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
To, że widzisz sieć z wywołaniem zwrotnym sieci, 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ć ograniczone do aplikacji uprzywilejowanych. Aby sprawdzić połączenie z internetem, zobacz NET_CAPABILITY_INTERNET i NET_CAPABILITY_VALIDATED.
Korzystanie z sieci w tle również podlega kontroli uprawnień. Jeśli aplikacja chce korzystać z sieci w tle, musi mieć uprawnienie CHANGE_NETWORK_STATE.
Aplikacje z tym uprawnieniem umożliwiają systemowi próbę wywołania sieci, która nie jest aktywna, np. sieci komórkowej, gdy urządzenie jest połączone z siecią Wi-Fi. Taka aplikacja wywołuje metodę ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback) z obiektem NetworkCallback, który ma zostać wywołany po uruchomieniu sieci.