Android umożliwia aplikacjom śledzenie dynamicznych zmian w łączności. Aby śledzić zmiany w połączeniach i na nie reagować, użyj tych klas:
ConnectivityManager
informuje aplikację o stanie łączności w systemie.- Klasa
Network
reprezentuje jedną z sieci, do których jest podłączone urządzenie. ObiektNetwork
możesz używać jako klucza do zbierania informacji o sieci za pomocą funkcjiConnectivityManager
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 sieci, takie jak lista serwerów DNS, adresy IP lokalne i trasy sieciowe zainstalowane w ramach sieci. - Obiekt
NetworkCapabilities
zawiera informacje o właściwościach sieci, takie jak transporty (Wi-Fi, komórkowy, Bluetooth) i możliwości sieci. Możesz na przykład wysłać zapytanie do obiektu, aby określić, czy sieć jest w stanie wysyłać wiadomości MMS, czy jest chroniona przez portal przechwytujący lub czy jest naliczana taryfa.
Aplikacje, które w danym momencie chcą znać bieżący stan połączenia, mogą wywoływać metody ConnectivityManager
, aby dowiedzieć się, jaka sieć jest dostępna. Metody te są pomocne w debugowaniu i pozwalają od czasu do czasu przejrzeć podsumowanie połączeń dostępnych 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ż dostosowywać zachowania aplikacji na podstawie odłączenia sieci lub zmiany jej możliwości.
Łączność może się zmienić w dowolnym momencie, a większość aplikacji musi mieć 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 niej istotne. Dzięki wywołaniu zwrotnemu aplikacja może natychmiast reagować na każdą istotną zmianę w połączeniu bez konieczności korzystania z drogiego pollingu, który może pomijać szybkie aktualizacje.
Korzystanie z funkcji NetworkCallback
i innych sposobów sprawdzania stanu połączeń urządzenia nie wymaga żadnego szczególnego uprawnienia.
Niektóre sieci wymagają jednak specjalnych uprawnień.
Na przykład mogą być sieci z ograniczonym dostępem niedostę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 o każdym wywołaniu znajdziesz w odpowiedniej dokumentacji.
Pobieranie stanu chwilkowego
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ć odwołanie do bieżącej domyślnej sieci aplikacji:
Kotlin
val currentNetwork = connectivityManager.getActiveNetwork()
Java
Network currentNetwork = connectivityManager.getActiveNetwork();
Gdy aplikacja odwołuje się do sieci, 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 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.
NetworkCapabilities i LinkProperties
Obiekty NetworkCapabilities
i LinkProperties
zawierają informacje o wszystkich atrybutach, które system zna w przypadku sieci.
Obiekt LinkProperties
zna trasy, adresy linków, nazwę interfejsu, informacje o serwerze proxy (jeśli występują) i serwery DNS. Aby pobrać potrzebne informacje, wywołaj odpowiednią metodę obiektu LinkProperties
.
Obiekt NetworkCapabilities
zawiera informacje o transportach sieci i ich możliwościach.
Transport to abstrakcja ośrodka fizycznego, przez który działa sieć. Typowymi przykładami transportu są Ethernet, Wi-Fi i mobilne.
Do transportu można też wykorzystać VPN-y 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 przez Wi-Fi, jak i sieci komórkowe. 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ą z konstant NetworkCapabilities.TRANSPORT_*
.
Umiejętność opisuje właściwość sieci. Przykładowe możliwości: MMS
, NOT_METERED
i INTERNET
. Sieć z możliwością wysyłania i odbierania wiadomości MMS może wysyłać i odbierać wiadomości MMS, 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ć, czy urządzenie ma odpowiednie możliwości, za pomocą metody NetworkCapabilities.hasCapability(int)
z jedną z konstant NetworkCapabilities.NET_CAPABILITY_*
.
Najbardziej przydatne stałe NET_CAPABILITY_*
to:
NET_CAPABILITY_INTERNET
: wskazuje, że sieć jest skonfigurowana do korzystania z internetu. Chodzi o konfigurację, a nie o rzeczywistą możliwość dotarcia 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 rzeczywistej łączności znajdziesz w artykuleNET_CAPABILITY_VALIDATED
.NET_CAPABILITY_NOT_METERED
: oznacza, że sieć nie jest objęta pomiarem użycia danych. Sieć jest klasyfikowana jako z limitem, gdy użytkownik jest wrażliwy na duże zużycie danych w ramach tego połączenia z powodu kosztów, ograniczeń dotyczących danych lub problemów z wydajnością baterii.NET_CAPABILITY_NOT_VPN
: oznacza, ż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 internetowym lub sieć, która nie zapewnia rozpoznawania nazw domen, nie ma tej funkcji. To najbliższe, co system może powiedzieć o sieci, która faktycznie zapewnia dostęp, chociaż zweryfikowana sieć może nadal podlegać filtrowaniu na podstawie adresu IP lub nagłej utraty łączności 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 funkcje, które mogą zainteresować bardziej wyspecjalizowane aplikacje.
Więcej informacji znajdziesz w definicjach parametrów w artykule NetworkCapabilities.hasCapability(int)
.
Możliwości sieci mogą się zmieniać w każdej chwili. Gdy system wykryje portal, wyświetla powiadomienie zapraszające użytkownika do zalogowania się. Podczas tego procesu sieć ma dostęp do funkcji NET_CAPABILITY_INTERNET
i NET_CAPABILITY_CAPTIVE_PORTAL
, ale nie do funkcji 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 funkcję NET_CAPABILITY_VALIDATED
i straci funkcję NET_CAPABILITY_CAPTIVE_PORTAL
.
Transport w sieci również może się dynamicznie zmieniać.
Sieć VPN może na przykład 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 uzyskać informacje 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 limitu danych przed sieciami z limitem danych oraz szybsze sieci przed wolniejszymi.
Gdy aplikacja wysyła żądanie sieciowe, na przykład HttpsURLConnection
, system spełnia to żądanie, korzystając z domyślnej sieci. Aplikacje mogą też wysyłać ruch w innych sieciach. Więcej informacji znajdziesz w sekcji dotyczącej dodatkowych sieci.
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 sieci domyślnej zostaną przymusowo zakończone. 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. Wdrożyć onCapabilitiesChanged(Network,NetworkCapabilities)
, onLinkPropertiesChanged(Network,LinkProperties)
lub oba te rozwiązania, aby odpowiednio reagować na zmiany w połączeniu.
W przypadku wywołania zwrotnego zarejestrowanego w registerDefaultNetworkCallback()
wartość onLost()
oznacza, że sieć utraciła status sieci domyślnej. Może być odłączony.
Możesz dowiedzieć się, z jakich transportów korzysta sieć domyślna, wysyłając zapytanie NetworkCapabilities.hasTransport(int)
, ale nie jest to dobry sposób na określenie przepustowości ani pomiaru natężenia ruchu w sieci. Aplikacja nie może zakładać, że Wi-Fi jest zawsze nielimitowane i zawsze zapewnia 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 NetworkCapabilities i LinkProperties.
Domyślnie metody wywołania są wywoływane w wątku łączności aplikacji, który jest oddzielnym wątkiem używanym przez ConnectivityManager
. Jeśli implementacja funkcji wywołujących ma wykonać dłuższą pracę, wywołaj je na osobnym wątku roboczym, używając wariantu ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler)
.
Jeśli nie chcesz już korzystać z tej funkcji, możesz ją anulować, dzwoniąc pod numer ConnectivityManager.unregisterNetworkCallback(NetworkCallback)
.
W tym celu możesz użyć onPause()
w Twojej głównej aktywności, zwłaszcza jeśli rejestrujesz połączenie zwrotne w onResume()
.
Sieci dodatkowe
Chociaż domyślna sieć jest jedyną odpowiednią siecią dla 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 dotyczy 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 już ustawiona jako domyślna.
Aplikacja tworzy NetworkRequest
, aby poinformować ConnectivityManager
, jakie sieci chce nasłuchiwać. Ten przykład pokazuje, jak utworzyć NetworkRequest
dla aplikacji, która interesuje się tylko nielimitowanymi połączeniami z internetem:
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 Twoja aplikacja jest informowana o wszystkich zmianach dotyczących nielimitowanych sieci w systemie.
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.
Zadzwoń pod numerConnectivityManager.unregisterNetworkCallback(NetworkCallback)
, gdy oddzwanianie nie jest już potrzebne. Aplikacja może jednocześnie rejestrować wiele wywołań zwrotnych sieci.
Dla wygody obiekt NetworkRequest
zawiera typowe funkcje, których wymaga większość aplikacji, w tym:
Podczas pisania aplikacji sprawdź domyślne wartości, aby sprawdzić, czy pasują do Twojego przypadku użycia. Usuń 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 zmian w łączności w sieciach, z którymi aplikacja nie wchodzi w interakcję.
Jeśli np. Twoja aplikacja musi wysyłać wiadomości MMS, dodaj NET_CAPABILITY_MMS
do NetworkRequest
, aby uniknąć wyświetlania powiadomień o tym, że nie można wysyłać wiadomości MMS w przypadku wszystkich sieci. Dodaj TRANSPORT_WIFI_AWARE
, jeśli Twoja aplikacja obsługuje tylko połączenia P2P przez Wi-Fi.
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 opisaliśmy sekwencję wywołań zwrotnych, które może otrzymać aplikacja, jeśli zarejestruje zarówno wywołanie zwrotne domyślne, jak i zwykłe wywołanie zwrotne na urządzeniu z dostępem do sieci komórkowej. W tym przykładzie urządzenie łączy się z dobrym punktem dostępu Wi-Fi, a następnie się z nim rozłącza. W tym przykładzie zakładamy też, że na urządzeniu włączone jest ustawienie Mobilna transmisja danych zawsze aktywna.
Harmonogram wygląda tak:
Gdy aplikacja wywołuje funkcję
registerNetworkCallback()
, funkcja wywołania zwrotnego natychmiast otrzymuje połączenia zonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w sieci komórkowej, ponieważ tylko ta sieć jest dostępna. Jeśli jest dostępna inna sieć, aplikacja otrzymuje też wywołania zwrotne dla tej sieci.
Rysunek 1. Stan aplikacji po wywołaniu funkcjiregisterNetworkCallback()
.Następnie aplikacja wywołuje metodę
registerDefaultNetworkCallback()
. Domyślny wywoływany adres sieci zaczyna odbierać połączenia na adresyonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w sieci komórkowej, ponieważ jest to sieć domyślna. Jeśli jest aktywna inna sieć inna niż domyślna, aplikacja nie może odbierać połączeń na sieć inną niż domyślna.
Rysunek 2. Stan aplikacji po zarejestrowaniu sieci domyślnej.Później urządzenie łączy się z siecią Wi-Fi (bez limitu). Zwykły wywołanie zwrotne sieci otrzymuje połączenia na numery
onAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w sieci Wi-Fi.
Rysunek 3. Stan aplikacji po połączeniu z nielimitowaną siecią Wi-Fi.W tym momencie może być konieczne sprawdzenie sieci Wi-Fi. W tym przypadku wywołania
onNetworkCapabilitiesChanged()
w ramach zwykłego wywołania zwrotnego sieci nie obejmują funkcjiNET_CAPABILITY_VALIDATED
. Po chwili otrzymuje ono wywołanie doonNetworkCapabilitiesChanged()
, gdzie nowe możliwości obejmująNET_CAPABILITY_VALIDATED
. W większości przypadków weryfikacja trwa bardzo krótko.Gdy sieć Wi-Fi jest prawidłowa, system preferuje ją od sieci komórkowej, głównie dlatego, że nie jest to sieć płatna. Sieć Wi-Fi staje się siecią domyślną, więc wywołanie zwrotne sieci domyślnej otrzymuje wywołanie do
onAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
dla sieci Wi-Fi. Sieć komórkowa przechodzi w tło, a zwykła sieć wywołuje sieć komórkową.onLosing()
W tym przykładzie zakładamy, że na tym urządzeniu dane mobilne są zawsze włączone, 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. Ponieważ połączenie Wi-Fi zostało utracone, regularny wywołanie zwrotne sieci otrzymuje połączenie z numeru
onLost()
dla Wi-Fi. Ponieważ sieć komórkowa jest nową siecią domyślną, wywołanie zwrotne sieci domyślnej odbiera połączenia na numeryonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w sieci komórkowej.
Rysunek 5. Stan aplikacji po rozłączeniu z 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 w przypadku połączeń onAvailable()
występuje krótki dodatkowy opóźnienie. Z sieci regularnych połączeń zwrotnych dochodzą też połączenia na numery onAvailable()
, onNetworkCapabilitiesChanged()
i onLinkPropertiesChanged()
, ponieważ staje się dostępny mobilny numer telefonu.
ograniczenia dotyczące korzystania z sieci na potrzeby przesyłania danych;
Możliwość wyświetlenia sieci za pomocą funkcji 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 inne mogą być dostępne tylko dla wybranych aplikacji. Aby sprawdzić połączenie z internetem, zapoznaj się z instrukcjami NET_CAPABILITY_INTERNET
i NET_CAPABILITY_VALIDATED
.
Korzystanie z sieci w tle również podlega kontroli uprawnień. Jeśli Twoja aplikacja chce korzystać z sieci w tle, musi mieć uprawnienie CHANGE_NETWORK_STATE
.
Aplikacje z tymi uprawnieniami umożliwiają systemowi próbę włączenia sieci, która jest wyłączona, np. sieci komórkowej, gdy urządzenie jest połączone z siecią Wi-Fi. Taka aplikacja wywołuje ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback)
z parametrem NetworkCallback
, który ma być wywoływany po uruchomieniu sieci.