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. Gdy sieć zostanie rozłączona, obiektNetwork
przestaje być dostępny. 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 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 to, co sieć może zrobić. Możesz na przykład wysłać zapytanie do obiektu, aby określić, czy sieć nie 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. Te metody są przydatne do debugowania i okresowego sprawdzania stanu połączenia w danym momencie.
Jednak metody synchroniczne
ConnectivityManager
nie informują aplikacji o niczym, co dzieje się po wywołaniu, więc nie pozwalają na aktualizowanie 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ń. 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();
Aplikacja może poprosić o informacje o danej sieci:
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 dodatkowych funkcji, zarejestruj konto NetworkCallback
.
Więcej informacji o rejestrowaniu wywołań zwrotnych sieci znajdziesz w artykule Odbieranie 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 fizycznego medium, w którym 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 jest sieć VPN działająca w sieci Wi-Fi i komórkowej. 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_*
.
Najprzydatniejsze 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 publicznych serwerów. Sieć może na przykład umożliwiać dostęp do internetu, ale wymagać korzystania z portalu przechwytującego.Sieć komórkowa operatora zwykle ma funkcję
INTERNET
, podczas gdy lokalna sieć Wi-Fi P2P zwykle jej nie ma. Informacje o rzeczywistej łączności znajdziesz w artykuleNET_CAPABILITY_VALIDATED
.NET_CAPABILITY_NOT_METERED
: wskazuje, że sieć nie jest objęta pomiarem użycia danych. Sieć jest klasyfikowana jako taryfowa, gdy użytkownik jest wrażliwy na duże zużycie danych w ramach tego połączenia z powodu kosztów finansowych, ograniczeń 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 utracie łączności z powodu problemów takich jak słaby sygnał.NET_CAPABILITY_CAPTIVE_PORTAL
: wskazuje, że sieć ma portal przechwytujący, gdy jest sprawdzana.
Istnieją też 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 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
.
Podobnie transporty sieci mogą się zmieniać dynamicznie.
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 dowiedzieć się więcej o zdarzeniach sieciowych, użyj klasy NetworkCallback
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, a sieci szybsze przed wolniejszymi.
Gdy aplikacja wysyła żądanie sieciowe, np. 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 domyślna może się zmienić w dowolnym momencie podczas istnienia aplikacji. Typowym przykładem jest urządzenie, które znajdzie się w zasięgu znanej, aktywnej, nielimitowanej i szybszej niż mobilna sieci Wi-Fi. Urządzenie łączy się z tym punktem dostępu i przełącza sieć domyślną 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 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 argumentu NetworkCapabilities.getLinkDownstreamBandwidthKbps()
do pomiaru przepustowości i NetworkCapabilites.hasCapability(int)
do określenia pomiaru.NET_CAPABILITY_NOT_METERED
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 uzyskać więcej informacji na ich temat, aplikacje tworzą NetworkRequest
dopasowane do swoich potrzeb i wywołują ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback)
.
Proces jest podobny do nasłuchiwania w sieci domyślnej. Chociaż w danym momencie może być tylko jedna sieć domyślna, która ma zastosowanie do aplikacji, ta wersja pozwala aplikacji widzieć wszystkie dostępne sieci jednocześnie. Dlatego wywołanie funkcji onLost(Network)
oznacza, że sieć została trwale odłączona, a nie że nie jest już domyślną.
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.
W przypadku domyślnego wywołania zwrotnego sieci istnieje wersja registerNetworkCallback(NetworkRequest, NetworkCallback, Handler)
, która akceptuje Handler
, więc nie wczytuje wątku Connectivity
w 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 potem 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 funkcję
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 odbiera 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 weryfikacja sieci Wi-Fi może potrwać chwilę. W tym przypadku wywołania
onNetworkCapabilitiesChanged()
w ramach zwykłego wywołania zwrotnego sieci nie obejmują funkcjiNET_CAPABILITY_VALIDATED
. Po chwili otrzymuje wywołanie doonNetworkCapabilitiesChanged()
, gdzie nowe możliwości obejmująNET_CAPABILITY_VALIDATED
. W większości przypadków weryfikacja przebiega bardzo szybko.Gdy sieć Wi-Fi jest prawidłowa, system preferuje ją od sieci komórkowej, głównie dlatego, że nie jest to sieć taryfowana. 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 do tła, a zwykły wywołanie zwrotne sieci wywołujeonLosing()
dla sieci komórkowej.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 chwili sieć komórkowa się rozłączy, a zwykły wywołujący z sieci otrzyma połączenie na numer
onLost()
.
Rysunek 4. Stan aplikacji po weryfikacji sieci Wi-Fi.Później urządzenie nagle rozłącza się z Wi-Fi, ponieważ znajduje się poza zasięgiem. Ponieważ połączenie Wi-Fi zostało utracone, regularny wywołujący sieci otrzymuje wywołanie do
onLost()
dla Wi-Fi. Ponieważ sieć komórkowa jest nową siecią domyślną, wywołanie zwrotne sieci domyślnej odbiera połączenia doonAvailable()
,onNetworkCapabilitiesChanged()
ionLinkPropertiesChanged()
w 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, gdy połączenie Wi-Fi zostanie utracone, 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 docierają też połączenia do onAvailable()
, onNetworkCapabilitiesChanged()
i onLinkPropertiesChanged()
, ponieważ staje się dostępny mobilny.
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 korzystać z 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 artykułem NET_CAPABILITY_INTERNET
i NET_CAPABILITY_VALIDATED
.
Używanie sieci w tle również podlega weryfikacji uprawnień. Jeśli 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 nie jest włą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.