ConnectivityManager getNetworkInfo (int) jest przestarzały


144

Używając compileSdkVersion 23 , próbując jednak obsługiwać już od 9.

getNetworkInfo(int)został wycofany w 23. Sugerowano użycie getAllNetworks()igetNetworkInfo(Network) w zamian. Jednak oba wymagają minimum API 21.

Czy istnieje klasa, której możemy użyć w pakiecie pomocy, która może w tym pomóc?

Wiem, że rozwiązanie zostało zaproponowane wcześniej , jednak wyzwanie, jakim są moje minimalne wymagania API wynoszące 9, stanowi problem.


możesz sprawdzić wersję kompilacji w czasie wykonywania i użyć odpowiedniej metody
stinepike

1
Czy to nadal spowoduje wyświetlenie przestarzałego ostrzeżenia?
kyleED

Sprawdź moją klasę ConnectivityObserver, która zawiera metody API poniżej i powyżej Androida Nougat.
JJD

Odpowiedzi:


166

Możesz użyć:

getActiveNetworkInfo ();

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) { 
    // connected to the internet
    if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
        // connected to wifi
    } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
        // connected to mobile data
    }
} else {
    // not connected to the internet
}

Lub w obudowie przełącznika

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) { 
    // connected to the internet
    switch (activeNetwork.getType()) {
        case ConnectivityManager.TYPE_WIFI:
            // connected to wifi
            break;
        case ConnectivityManager.TYPE_MOBILE:
            // connected to mobile data
            break;
        default:
            break;
    }
} else {
    // not connected to the internet
}

1
@ShirishHerwade - Tak, odbiornik transmisji nie jest potrzebny w tym przypadku. Funkcja getActiveNetworkInfo () może zostać umieszczona w jej własnej metodzie, pod warunkiem uwzględnienia odwołania do kontekstu.
Chleb

1
@TheIT - Tak, dokument mówi: „Przed zainicjowaniem ruchu sieciowego należy zawsze sprawdzić isConnected ()”. To rozwiązanie nie inicjuje ruchu i zapewnia jedynie rozwiązanie dla przestarzałego wywołania getNetworkInfo ().
Chleb

7
Począwszy od Androida 9, SDK 28 jest przestarzałe.
Zbarcea Christian

32
activeNetwork.getType()jest przestarzały i ConnectivityManager.TYPE_WIFIprzestarzały
Godwin

7
Wymiana jest terazcm.getNetworkCapabilities(cm.activeNetwork).hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
tmm1

63

Od października 2018 roku zaakceptowana odpowiedź jest przestarzała.

getType()i same typy są teraz przestarzałe na poziomie 28 interfejsu API. Z Javadoc:

Dzwoniący powinni przełączyć się na sprawdzanie możliwości sieciowych # hasTransport zamiast jednej ze stałych NetworkCapabilities # TRANSPORT *

Aby użyć NetworkCapabilities, musisz przekazać Networkinstancję do getNetworkCapabilities()metody. Aby uzyskać tę instancję, musisz zadzwonićgetActiveNetwork() który został dodany na poziomie API 23.

Dlatego uważam, że na razie właściwym sposobem bezpiecznego sprawdzenia, czy masz połączenie z Wi-Fi lub siecią komórkową, jest:

public static boolean isNetworkConnected() {
    final ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (cm != null) {
        if (Build.VERSION.SDK_INT < 23) {
            final NetworkInfo ni = cm.getActiveNetworkInfo();

            if (ni != null) {
                return (ni.isConnected() && (ni.getType() == ConnectivityManager.TYPE_WIFI || ni.getType() == ConnectivityManager.TYPE_MOBILE));
            }
        } else {
            final Network n = cm.getActiveNetwork();

            if (n != null) {
                final NetworkCapabilities nc = cm.getNetworkCapabilities(n);

                return (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
            }
        } 
    }

    return false; 
}

Możesz również sprawdzić inne typy TRANSPORT, które znajdziesz tutaj .

Ważna uwaga: jeśli masz połączenie z Wi-Fi i VPN, Twój obecny stan może byćTRANSPORT_VPN , więc możesz również to sprawdzić.

Nie zapomnij dodać następujących uprawnień do pliku AndroidManifest:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Czy hasTransport (NetworkCapabilities.TRANSPORT_WIFI) jest odpowiednikiem ni.isConnected () && (ni.getType () == ConnnectivityManager.TYPE_WIFI)? Chodzi mi o to, czy funkcja hasTransport () również sprawdza, czy urządzenie jest podłączone lub próbuje się połączyć?
Biscuit

Po raz kolejny NetworkInfojest amortyzowany, nie możesz już używać NetWorkInfo, więc jak to stanowi alternatywę?
Prescott Chartier

@PrescottChartier ten fragment kodu uzyskuje dostęp tylko do NetworkInfo na urządzeniach SDK <23
Tom

59

Aktualizacja z lutego 2020 r .:

Zaakceptowana odpowiedź jest ponownie przestarzała w programie 28 (Android P), ale jej metoda zastępowania działa tylko w 23 (Android M). Aby obsługiwać starsze urządzenia, napisałem funkcję pomocniczą w.

Jak używać:

int type = getConnectionType(getApplicationContext());

Zwraca wartość int, którą możesz zmienić enumw swoim kodzie:

0: Brak dostępu do Internetu (może w trybie samolotowym lub w trakcie łączenia się z Wi-Fi).

1: komórkowy (dane mobilne, 3G / 4G / LTE cokolwiek).

2: Wi-Fi.

3: VPN

Możesz skopiować wersję Kotlin lub Java funkcji pomocniczej.

Kotlin:

@IntRange(from = 0, to = 3)
fun getConnectionType(context: Context): Int {
    var result = 0 // Returns connection type. 0: none; 1: mobile data; 2: wifi
    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        cm?.run {
            cm.getNetworkCapabilities(cm.activeNetwork)?.run {
                if (hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    result = 2
                } else if (hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    result = 1
                } else if (hasTransport(NetworkCapabilities.TRANSPORT_VPN)){
                    result = 3
                }
            }
        }
    } else {
        cm?.run {
            cm.activeNetworkInfo?.run {
                if (type == ConnectivityManager.TYPE_WIFI) {
                    result = 2
                } else if (type == ConnectivityManager.TYPE_MOBILE) {
                    result = 1
                } else if(type == ConnectivityManager.TYPE_VPN) {
                    result = 3
                }
            }
        }
    }
    return result
}

Jawa:

@IntRange(from = 0, to = 3)
public static int getConnectionType(Context context) {
    int result = 0; // Returns connection type. 0: none; 1: mobile data; 2: wifi
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (cm != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            if (capabilities != null) {
                if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    result = 2;
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    result = 1;
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
                    result = 3;
                }
            }
        }
    } else {
        if (cm != null) {
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            if (activeNetwork != null) {
                // connected to the internet
                if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                    result = 2;
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                    result = 1;
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_VPN) {
                    result = 3;
                }
            }
        }
    }
    return result;
}

2
Ponieważ możliwe są 2 wyniki, lepiej jest użyć wartości logicznej zamiast zwracać liczbę całkowitą ...
Christian

3
@Christian Jak wyjaśniono w żółtej części, funkcja ta zwraca pomocnik 3 możliwych stanów: No Internet, Cellulari Wi-Fi. Jeśli nie zależy Ci na typie połączenia, możesz zmodyfikować kod, aby pasował do Twojej aplikacji.
user1032613

1
A co z komentarzem w powyższym rozwiązaniu „jeśli masz połączenie z Wi-Fi i VPN, to Twój aktualny stan może być TRANSPORT_VPN, więc możesz też chcieć to sprawdzić.”?
David

1
@Lukas, musisz być ostrożny, jeśli używasz Booleanklasy opakowującej, zamiast booleanktórej jest prymitywna. W oświadczeniu if będziesz musiał dodać czek na null. A co, jeśli jutro zostanie wprowadzony kolejny nowy tryb transportu w NetworkCapabilities ... więc użycie liczb całkowitych do rozgałęziania pomoże, a także możesz przejść do przypadków przełączania.
Shadow Droid

3
jestem zmęczony tym ciągłym cyklem deprecjacji
Segun Wahaab

16

Zaktualizowana odpowiedź (19:07: 2018):

Ta metoda pomoże Ci sprawdzić, czy połączenie internetowe jest dostępne.

public static boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (connectivityManager != null) {
        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
        return (activeNetwork != null && activeNetwork.isConnectedOrConnecting());
    } else {
        return false;
    }
}

Stara odpowiedź:

Aby uzyskać najlepszą praktykę ponownego wykorzystania kodu, improwizuj odpowiedź Cheese Bread.

public static boolean isNetworkAvailable(Context context) {
    int[] networkTypes = {ConnectivityManager.TYPE_MOBILE,
            ConnectivityManager.TYPE_WIFI};
    try {
        ConnectivityManager connectivityManager =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        for (int networkType : networkTypes) {
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            if (activeNetworkInfo != null &&
                    activeNetworkInfo.getType() == networkType)
                return true;
        }
    } catch (Exception e) {
        return false;
    }
    return false;
}

Kod można umieścić w klasie Util i można go użyć do sprawdzenia, czy telefon jest podłączony do Internetu przez Wi-Fi lub Internet mobilny z dowolnej części aplikacji.


3
Sugerowałbym przeniesienie pobierania aktywnej sieci poza pętlę for.
shtolik

20
activeNetwork.isConnectedOrConnecting()jest teraz przestarzały
MHSFisher

1
Zmieniam activeNetwork.isConnectedOrConnecting () na activeNetwork.isConnected
Murillo Comino

NetworkInfo jest teraz przestarzałe. Trzeba jeszcze raz zaktualizować!
Scott Biggs

13

Zaakceptowana odpowiedź jest przestarzała w wersji 28, więc oto rozwiązanie, którego używam w moim projekcie.

Zwraca typ połączenia. fałsz: brak połączenia internetowego; prawda: dane mobilne || wifi

public static boolean isNetworkConnected(Context context) { 
    boolean result = false; 
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (cm != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            if (capabilities != null) {
                if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    result = true;
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    result = true;
                }
            }
        }
    } else {
        if (cm != null) {
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            if (activeNetwork != null) {
                // connected to the internet
                if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                    result = true;
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                    result = true;
                }
            }
        }
    }
    return result;
}

2
activeNetwork.getType () również jest przestarzała. Możesz użyć activeNetwork.isConnected ();
Aman Verma,

11

Istnieje aktualizacja tej odpowiedzi od marca 2020 r., Która obsługuje API.15 do API.29, można ją znaleźć po oryginalnej odpowiedzi

Odpowiedź z lutego 2019 r

Aby sprawdzić, czy jesteś online:

boolean isOnline() {
    // Checking internet connectivity
    ConnectivityManager connectivityMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = null;
    if (connectivityMgr != null) {
        activeNetwork = connectivityMgr.getActiveNetworkInfo();
    }
    return activeNetwork != null;
}

Aby uzyskać typ połączenia internetowego przed / po Androidzie M.

void internetType() {
    // Checking internet connectivity
    ConnectivityManager connectivityMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = null;
    if (connectivityMgr != null) {
        activeNetwork = connectivityMgr.getActiveNetworkInfo();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            NetworkCapabilities nc = connectivityMgr.getNetworkCapabilities(connectivityMgr.getActiveNetwork());
            if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                // connected to mobile data
            } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                // connected to wifi
            }
        } else {
            if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                // connected to wifi
            } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                // connected to mobile data
            }
        }
    }
}

Wszystkie przypadki wymagają pozwolenia na dostęp do stanu sieci

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Aktualizacja z marca 2020 r

Jak NetworkInfojest przestarzałe i od API 29 od teraz musimy używać ConnectivityManager.NetworkCallbackjego zmiany stanu sieci onAvailable()i onLost()wywołań zwrotnych.

Stosowanie:

  • Możesz użyć tej biblioteki lub bezpośrednio użyć poniższej klasy narzędziowej, która jest częścią tej biblioteki.

cechy

  • Jest świadomy cyklu życia, wdrażając go, LifecycleObserveraby uniknąć wycieku pamięci, wykonując pewne porządki wonDestroy() metodzie.
  • Obsługuje od API 15 (Ice Cream Sandwich) do API 29 (Android Q)
  • W przypadku interfejsów API starszych niż API 21 używa kontekstowego BoradcastReceiveri NetworkInfoi używaConnectivityManager.NetworkCallback do API 21 i powyżej.
  • Gdy włączone są zarówno sieci Wi-Fi, jak i komórkowe, słuchacz łączności nie przerywa połączenia po rozłączeniu Wi-Fi podczas przechodzenia do sieci komórkowej.
  • Gdy sieć komórkowa jest włączona, nasłuchiwanie łączności nie przerywa, gdy Wi-Fi jest podłączone i jest siecią aktywną (ponieważ jest to sieć preferowana).
  • Jeśli zamierzasz korzystać z biblioteki, nie musisz dołączać tego uprawnienia android.permission.ACCESS_NETWORK_STATE; ale musisz ją dołączyć, jeśli zamierzasz używać klasy użytkowej.

Możliwości

  • Uzyskaj aktualny stan łączności (online / offline).
  • Ciągłe sprawdzanie / odsłuchiwanie połączenia internetowego i wywoływanie oddzwonienia, gdy urządzenie przechodzi w tryb offline lub online.
  • Uzyskaj typ aktywnego połączenia internetowego (WiFi lub komórkowe).
  • Uzyskaj typ wszystkich dostępnych sieci (Wi-Fi lub komórkowa). >> Obsługiwane tylko w API 21+
  • Sprawdź liczbę wszystkich dostępnych sieci >> Obsługiwane tylko w API 21+
@RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
public class ConnectionUtil implements LifecycleObserver {

    private static final String TAG = "LOG_TAG";
    private ConnectivityManager mConnectivityMgr;
    private Context mContext;
    private NetworkStateReceiver mNetworkStateReceiver;

    /*
     * boolean indicates if my device is connected to the internet or not
     * */
    private boolean mIsConnected = false;
    private ConnectionMonitor mConnectionMonitor;


    /**
     * Indicates there is no available network.
     */
    private static final int NO_NETWORK_AVAILABLE = -1;


    /**
     * Indicates this network uses a Cellular transport.
     */
    public static final int TRANSPORT_CELLULAR = 0;


    /**
     * Indicates this network uses a Wi-Fi transport.
     */
    public static final int TRANSPORT_WIFI = 1;


    public interface ConnectionStateListener {
        void onAvailable(boolean isAvailable);
    }


    public ConnectionUtil(Context context) {
        mContext = context;
        mConnectivityMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        ((AppCompatActivity) mContext).getLifecycle().addObserver(this);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mConnectionMonitor = new ConnectionMonitor();
            NetworkRequest networkRequest = new NetworkRequest.Builder()
                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                    .build();
            mConnectivityMgr.registerNetworkCallback(networkRequest, mConnectionMonitor);
        }

    }


    /**
     * Returns true if connected to the internet, and false otherwise
     *
     * <p>
     * NetworkInfo is deprecated in API 29
     * https://developer.android.com/reference/android/net/NetworkInfo
     * <p>
     * getActiveNetworkInfo() is deprecated in API 29
     * https://developer.android.com/reference/android/net/ConnectivityManager#getActiveNetworkInfo()
     * <p>
     * getNetworkInfo(int) is deprecated as of API 23
     * https://developer.android.com/reference/android/net/ConnectivityManager#getNetworkInfo(int)
     */
    public boolean isOnline() {

        mIsConnected = false;

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            // Checking internet connectivity
            NetworkInfo activeNetwork = null;
            if (mConnectivityMgr != null) {
                activeNetwork = mConnectivityMgr.getActiveNetworkInfo(); // Deprecated in API 29
            }
            mIsConnected = activeNetwork != null;

        } else {
            Network[] allNetworks = mConnectivityMgr.getAllNetworks(); // added in API 21 (Lollipop)

            for (Network network : allNetworks) {
                NetworkCapabilities networkCapabilities = mConnectivityMgr.getNetworkCapabilities(network);
                if (networkCapabilities != null) {
                    if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                            || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
                            || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET))
                        mIsConnected = true;
                }
            }
        }

        return mIsConnected;

    }


    /**
     * Returns
     * <p> <p>
     * <p><p> NO_NETWORK_AVAILABLE >>> when you're offline
     * <p><p> TRANSPORT_CELLULAR >> When Cellular is the active network
     * <p><p> TRANSPORT_WIFI >> When Wi-Fi is the Active network
     * <p>
     */
    public int getActiveNetwork() {

        NetworkInfo activeNetwork = mConnectivityMgr.getActiveNetworkInfo(); // Deprecated in API 29
        if (activeNetwork != null)

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                NetworkCapabilities capabilities = mConnectivityMgr.getNetworkCapabilities(mConnectivityMgr.getActiveNetwork());
                if (capabilities != null)
                    if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                        // connected to mobile data
                        return TRANSPORT_CELLULAR;

                    } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                        // connected to wifi
                        return TRANSPORT_WIFI;
                    }

            } else {
                if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) { // Deprecated in API 28
                    // connected to mobile data
                    return TRANSPORT_CELLULAR;

                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) { // Deprecated in API 28
                    // connected to wifi
                    return TRANSPORT_WIFI;
                }
            }
        return NO_NETWORK_AVAILABLE;
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public int getAvailableNetworksCount() {

        int count = 0;

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            Network[] allNetworks = mConnectivityMgr.getAllNetworks(); // added in API 21 (Lollipop)
            for (Network network : allNetworks) {
                NetworkCapabilities networkCapabilities = mConnectivityMgr.getNetworkCapabilities(network);
                if (networkCapabilities != null)
                    if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                            || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
                        count++;
            }

        }

        return count;
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public List<Integer> getAvailableNetworks() {

        List<Integer> activeNetworks = new ArrayList<>();

        Network[] allNetworks; // added in API 21 (Lollipop)
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            allNetworks = mConnectivityMgr.getAllNetworks();
            for (Network network : allNetworks) {
                NetworkCapabilities networkCapabilities = mConnectivityMgr.getNetworkCapabilities(network);
                if (networkCapabilities != null) {
                    if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
                        activeNetworks.add(TRANSPORT_WIFI);

                    if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
                        activeNetworks.add(TRANSPORT_CELLULAR);

                }
            }
        }

        return activeNetworks;
    }


    public void onInternetStateListener(ConnectionStateListener listener) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            mNetworkStateReceiver = new NetworkStateReceiver(listener);
            IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
            mContext.registerReceiver(mNetworkStateReceiver, intentFilter);

        } else {
            mConnectionMonitor.setOnConnectionStateListener(listener);
        }
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy() {
        Log.d(TAG, "onDestroy");
        ((AppCompatActivity) mContext).getLifecycle().removeObserver(this);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (mConnectionMonitor != null)
                mConnectivityMgr.unregisterNetworkCallback(mConnectionMonitor);
        } else {
            if (mNetworkStateReceiver != null)
                mContext.unregisterReceiver(mNetworkStateReceiver);
        }

    }


    public class NetworkStateReceiver extends BroadcastReceiver {

        ConnectionStateListener mListener;

        public NetworkStateReceiver(ConnectionStateListener listener) {
            mListener = listener;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getExtras() != null) {

                NetworkInfo activeNetworkInfo = mConnectivityMgr.getActiveNetworkInfo(); // deprecated in API 29

                /*
                 * activeNetworkInfo.getState() deprecated in API 28
                 * NetworkInfo.State.CONNECTED deprecated in API 29
                 * */
                if (!mIsConnected && activeNetworkInfo != null && activeNetworkInfo.getState() == NetworkInfo.State.CONNECTED) {
                    Log.d(TAG, "onReceive: " + "Connected To: " + activeNetworkInfo.getTypeName());
                    mIsConnected = true;
                    mListener.onAvailable(true);

                } else if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
                    if (!isOnline()) {
                        mListener.onAvailable(false);
                        mIsConnected = false;
                    }

                }

            }
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public class ConnectionMonitor extends ConnectivityManager.NetworkCallback {

        private ConnectionStateListener mConnectionStateListener;

        void setOnConnectionStateListener(ConnectionStateListener connectionStateListener) {
            mConnectionStateListener = connectionStateListener;
        }

        @Override
        public void onAvailable(@NonNull Network network) {

            if (mIsConnected)
                return;

            Log.d(TAG, "onAvailable: ");

            if (mConnectionStateListener != null) {
                mConnectionStateListener.onAvailable(true);
                mIsConnected = true;
            }

        }

        @Override
        public void onLost(@NonNull Network network) {

            if (getAvailableNetworksCount() == 0) {
                mConnectionStateListener.onAvailable(false);
                mIsConnected = false;
            }

        }

    }

}

@Rasel, sprawdź zaktualizowaną odpowiedź, mam nadzieję, że może to pomóc
Zain

Jeśli użytkownik jest podłączony do Wi-Fi i danych mobilnych w tym samym czasie i utraci połączenie w jednym z nich, onLostzostanie wezwany. onLostnie oznacza, że ​​urządzenie utraciło połączenie z Internetem, ale sieć utraciła połączenie.
Gokhan Arik

@Gokhan Arik .. Niezły haczyk Pracuję nad rozwiązaniem tego problemu
Zain


@GokhanArik dzięki za pomoc .. Właśnie zaktualizowałem moją odpowiedź i rozszerzyłem użycie API, proszę daj mi znać, jeśli zauważysz jakieś błędy
Zain

4

Dobrze jest sprawdzić, czy Twoja sieć jest połączona z Internetem:

@Suppress("DEPRECATION")
fun isNetworkAvailable(context: Context): Boolean {
    try {
        val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        return if (Build.VERSION.SDK_INT > 22) {
            val an = cm.activeNetwork ?: return false
            val capabilities = cm.getNetworkCapabilities(an) ?: return false
            capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        } else {
            val a = cm.activeNetworkInfo ?: return false
            a.isConnected && (a.type == ConnectivityManager.TYPE_WIFI || a.type == ConnectivityManager.TYPE_MOBILE)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return false
}

Możesz też chcieć to sprawdzić NetworkCapabilities.NET_CAPABILITY_VALIDATED.
JJD,

3

Wersja Kotlin:

fun isInternetOn(context: Context): Boolean {
   val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
   val activeNetwork = cm?.activeNetworkInfo
   return activeNetwork != null && activeNetwork.isConnected
}

3

Zgodnie z sugestią Cheese Bread użyj metody getActiveNetworkInfo ()

getActiveNetworkInfo

Dodano na poziomie API 1

NetworkInfo getActiveNetworkInfo ()

Zwraca szczegółowe informacje o aktualnie aktywnej domyślnej sieci danych. Po połączeniu ta sieć jest domyślną trasą połączeń wychodzących. Przed zainicjowaniem ruchu sieciowego należy zawsze sprawdzić isConnected (). Może to zwrócić wartość null, jeśli nie ma domyślnej sieci. Ta metoda wymaga od wywołującego posiadania uprawnienia ACCESS_NETWORK_STATE. Zwraca NetworkInfo obiekt NetworkInfo dla bieżącej domyślnej sieci lub wartość null, jeśli żadna domyślna sieć nie jest obecnie aktywna.

Odniesienie: Android Studio

 public final boolean isInternetOn() {

    // get Connectivity Manager object to check connection
    ConnectivityManager connec =
            (ConnectivityManager)getSystemService(getBaseContext().CONNECTIVITY_SERVICE);

    // Check for network connections
    if ( connec.getActiveNetworkInfo().getState() == android.net.NetworkInfo.State.CONNECTED ||
            connec.getActiveNetworkInfo().getState() == android.net.NetworkInfo.State.CONNECTING ) {

        // if connected with internet

        Toast.makeText(this, connec.getActiveNetworkInfo().getTypeName(), Toast.LENGTH_LONG).show();
        return true;

    } else if (
            connec.getActiveNetworkInfo().getState() == android.net.NetworkInfo.State.DISCONNECTED ||
                    connec.getActiveNetworkInfo().getState() == android.net.NetworkInfo.State.DISCONNECTED  ) {

        Toast.makeText(this, " Not Connected ", Toast.LENGTH_LONG).show();
        return false;
    }
    return false;
}

teraz wywołaj metodę, dla bezpiecznego użycia spróbuj złapać

try {
    if (isInternetOn()) { /* connected actions */ }
    else { /* not connected actions */ }
} catch (Exception e){
  Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}

I nie zapomnij dodać:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

dziękuję, to przydatne. kiedy sprawdzamy stan sieci i czy Wi-Fi i dane są wyłączone - w tym czasie aplikacja ulega awarii, ale spróbuj złapać, aby rozwiązać problem ..
Rucha Bhatt Joshi

Jednak to nie działa, jeśli chcę sprawdzić, czy istnieje określony typ sieci, getNetworkInfo(ConnectivityManager.TYPE_ETHERNET).isAvailable
wylicz

3
getState () przestarzałe!
Diego Venâncio

Kilka przestarzałych instrukcji!
Scott Biggs

2

Aby być po bezpiecznej stronie, proponuję zastosować również metodę

NetworkInfo.isConnected ()

Cała metoda może wyglądać następująco:

/**
 * Checking whether network is connected
 * @param context Context to get {@link ConnectivityManager}
 * @return true if Network is connected, else false
 */
public static boolean isConnected(Context context){
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork != null && activeNetwork.isConnected()) {
        int networkType = activeNetwork.getType();
        return networkType == ConnectivityManager.TYPE_WIFI || networkType == ConnectivityManager.TYPE_MOBILE;
    } else {
        return false;
    }
}

9
activeNetwork.getType()jest przestarzały i ConnectivityManager.TYPE_WIFI przestarzały
Godwin

2

Oto jak mogę sprawdzić, czy obecna sieć korzysta z sieci komórkowej w najnowszych wersjach Androida:

val isCellular: Boolean get() {
    val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        cm.getNetworkCapabilities(cm.activeNetwork).hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
    } else {
        cm.activeNetworkInfo?.type == ConnectivityManager.TYPE_MOBILE
    }
}

2

(Prawie) Wszystkie odpowiedzi są przestarzałe w systemie Android P, więc oto C#rozwiązanie ( które jest łatwe do naśladowania dla programistów Java )

public bool IsOnline(Context context)
{
    var cm = (ConnectivityManager)context.GetSystemService(Context.ConnectivityService);

    if (cm == null) return false;

    if (Build.VERSION.SdkInt < BuildVersionCodes.M)
    {
        var ni = cm.ActiveNetworkInfo;

        if (ni == null) return false;

        return ni.IsConnected && (ni.Type == ConnectivityType.Wifi || ni.Type == ConnectivityType.Mobile);
    }

    return cm.GetNetworkCapabilities(cm.ActiveNetwork).HasTransport(Android.Net.TransportType.Wifi)
        || cm.GetNetworkCapabilities(cm.ActiveNetwork).HasTransport(Android.Net.TransportType.Cellular);
}   

Kluczem jest tutaj Android.Net.TransportType


Aaaannnndddd wszystko w tym jest PRZERWANE!
Prescott Chartier

@PrescottChartier w jakiej wersji?
Mehdi Dehghani

2

Być może będziemy musieli sprawdzić łączność internetową więcej niż raz. Będzie nam więc łatwiej, jeśli napiszemy blok kodu w metodzie rozszerzającej Context. Poniżej znajdują się moje rozszerzenia pomocnicze dla Contexti Fragment.

Sprawdzanie połączenia internetowego

fun Context.hasInternet(): Boolean {
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    return if (Build.VERSION.SDK_INT < 23) {
        val activeNetworkInfo = connectivityManager.activeNetworkInfo
        activeNetworkInfo != null && activeNetworkInfo.isConnected
    } else {
        val nc = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
        if (nc == null) {
            false
        } else {
            nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                    nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
        }
    }
}

Inne rozszerzenia

fun Context.hasInternet(notifyNoInternet: Boolean = true, trueFunc: (internet: Boolean) -> Unit) {
    if (hasInternet()) {
        trueFunc(true)
    } else if (notifyNoInternet) {
        Toast.makeText(this, "No Internet Connection!", Toast.LENGTH_SHORT).show()
    }
}

fun Context.hasInternet(
    trueFunc: (internet: Boolean) -> Unit,
    falseFunc: (internet: Boolean) -> Unit
) {
    if (hasInternet()) {
        trueFunc(true)
    } else {
        falseFunc(true)
    }
}

fun Fragment.hasInternet(): Boolean = context!!.hasInternet()

fun Fragment.hasInternet(notifyNoInternet: Boolean = true, trueFunc: (internet: Boolean) -> Unit) =
    context!!.hasInternet(notifyNoInternet, trueFunc)

fun Fragment.hasInternet(
    trueFunc: (internet: Boolean) -> Unit, falseFunc: (internet: Boolean) -> Unit
) = context!!.hasInternet(trueFunc, falseFunc)

2

sprawdź, czy Internet jest dostępny

@RequiresPermission(allOf = [
    Manifest.permission.ACCESS_NETWORK_STATE, 
    Manifest.permission.INTERNET
])
fun isInternetAvailable(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
    val activeNetworkInfo = connectivityManager!!.activeNetworkInfo
    return activeNetworkInfo != null && activeNetworkInfo.isConnected
}

2

connectivityManager.getActiveNetwork () nie występuje w poniższym systemie Android M (API 28). networkInfo.getState () jest przestarzała w porównaniu z systemem Android L.

Tak więc ostateczna odpowiedź brzmi:

public static boolean isConnectingToInternet(Context mContext) {
    if (mContext == null) return false;

    ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager != null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            final Network network = connectivityManager.getActiveNetwork();
            if (network != null) {
                final NetworkCapabilities nc = connectivityManager.getNetworkCapabilities(network);

                return (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                        nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
            }
        } else {
            NetworkInfo[] networkInfos = connectivityManager.getAllNetworkInfo();
            for (NetworkInfo tempNetworkInfo : networkInfos) {
                if (tempNetworkInfo.isConnected()) {
                    return true;
                }
            }
        }
    }
    return false;
}

1
Mówisz, że getActiveNetwork () nie występuje w Androidzie poniżej M, ale Twój kod używa go w Lollipop!?
3c71

2

Wiele odpowiedzi nadal używa getNetworkType poniżej 23, który jest przestarzały; użyj poniższego kodu, aby sprawdzić, czy urządzenie ma połączenie z Internetem.

public static boolean isNetworkConnected(Context context) {

    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (cm != null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            return capabilities != null && (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR));
        } else {
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            return activeNetwork != null && activeNetwork.isConnected();
        }
    }

    return false;
}

..

I nie zapomnij dodać tej linii w Manifest

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

1

Ponieważ opublikowane odpowiedzi pozwalają tylko na zapytanie o aktywną sieć, oto jak uzyskać dostęp NetworkInfodo dowolnej sieci, nie tylko aktywnej (na przykład sieć Wi-Fi) (przepraszam, kod Kotlin przed nami)

(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).run {
    allNetworks.find { getNetworkInfo(it).type == ConnectivityManager.TYPE_WIFI }?.let { network -> getNetworkInfo(network) }
//    getNetworkInfo(ConnectivityManager.TYPE_WIFI).isAvailable // This is the deprecated API pre-21
}

Wymaga to API 21 lub nowszego i pozwolenia android.permission.ACCESS_NETWORK_STATE


1
currentNetwork.getType () i ConnectivityManager.TYPE_WIFI są przestarzałe w API 28.
Abushawish

@Abushawish Jakie jest zalecane rozwiązanie dla API 28?
tmm1

Wymiana jest terazcm.getNetworkCapabilities(cm.activeNetwork).hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
tmm1

1

NetManager , którego możesz użyć do sprawdzenia połączenia internetowego w systemie Android za pomocą Kotlin

Jeśli używasz minSdkVersion> = 23

class NetManager @Inject constructor(var applicationContext: Context) {
    val isConnectedToInternet: Boolean?
        get() = with(
            applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE)
                    as ConnectivityManager
        ) {
            isConnectedToInternet()
        }
}

fun ConnectivityManager.isConnectedToInternet() = isConnected(getNetworkCapabilities(activeNetwork))

fun isConnected(networkCapabilities: NetworkCapabilities?): Boolean {
    return when (networkCapabilities) {
        null -> false
        else -> with(networkCapabilities) { hasTransport(TRANSPORT_CELLULAR) || hasTransport(TRANSPORT_WIFI) }
    }
}

Jeśli używasz minSdkVersion <23

class NetManager @Inject constructor(var applicationContext: Context) {
    val isConnectedToInternet: Boolean?
        get() = with(
            applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE)
                    as ConnectivityManager
        ) {
            isConnectedToInternet()
        }
}

fun ConnectivityManager.isConnectedToInternet(): Boolean = if (Build.VERSION.SDK_INT < 23) {
    isConnected(activeNetworkInfo)
} else {
    isConnected(getNetworkCapabilities(activeNetwork))
}


fun isConnected(network: NetworkInfo?): Boolean {
    return when (network) {
        null -> false
        else -> with(network) { isConnected && (type == TYPE_WIFI || type == TYPE_MOBILE) }
    }
}

fun isConnected(networkCapabilities: NetworkCapabilities?): Boolean {
    return when (networkCapabilities) {
        null -> false
        else -> with(networkCapabilities) { hasTransport(TRANSPORT_CELLULAR) || hasTransport(TRANSPORT_WIFI) }
    }
}

1

https://www.agnosticdev.com/content/how-detect-network-connectivity-android

postępuj zgodnie z tym samouczkiem, który powinien pomóc każdemu, kto szuka odpowiedzi.

uwaga networkInfo jest przestarzałe, dlatego zamień to isNetworkReacheable () na odpowiedź @vidha poniżej, przekazując getApplicationContext () jako parametr

  public static boolean isNetworkReacheable(Context context) {
    boolean result = false;
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (cm != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            if (capabilities != null) {
                if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    result = true;
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    result = true;
                }
            }
        }
    } else {
        if (cm != null) {
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            if (activeNetwork != null) {
                // connected to the internet
                if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                    result = true;
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                    result = true;
                }
            }
        }
    }
    return result;
}

0
public boolean isConnectedToWifi(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager == null) {
        return false;
    }

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        Network network = connectivityManager.getActiveNetwork();
        NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
        if (capabilities == null) {
            return false;
        }
        return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
    } else {
        NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        if (networkInfo == null) {
            return false;
        }
        return networkInfo.isConnected();
    }
}

0

U mnie to działa w Kotlinie. Wiele interfejsów API jest przestarzałych w klasie Network Manager, więc poniższa odpowiedź obejmuje całą obsługę API.

fun isNetworkAvailable(context: Context): Boolean {
    var result = false
    (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                result = isCapableNetwork(this,this.activeNetwork)
            } else {
                val networkInfos = this.allNetworks
                for (tempNetworkInfo in networkInfos) {
                    if(isCapableNetwork(this,tempNetworkInfo))
                        result =  true
                }
            }
        }

    return result
}

fun isCapableNetwork(cm: ConnectivityManager,network: Network?): Boolean{
     cm.getNetworkCapabilities(network)?.also {
        if (it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            return true
        } else if (it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            return true
        }
    }
    return false
}

Dodasz również poniżej

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

0

Poniższy kod działa na wszystkich interfejsach API. (Kotlin)

Jednak metoda getActiveNetworkInfo () jest przestarzała tylko w API 29 i działa na wszystkich interfejsach API, więc możemy jej używać we wszystkich interfejsach API poniżej 29

fun isInternetAvailable(context: Context): Boolean {
            var result = false
            val connectivityManager =
                context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val networkCapabilities = connectivityManager.activeNetwork ?: return false
                val actNw =
                    connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
                result = when {
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                    else -> false
                }
            } else {
                connectivityManager.run {
                    connectivityManager.activeNetworkInfo?.run {
                        result = when (type) {
                            ConnectivityManager.TYPE_WIFI -> true
                            ConnectivityManager.TYPE_MOBILE -> true
                            ConnectivityManager.TYPE_ETHERNET -> true
                            else -> false
                        }

                    }
                }
            }

            return result
        }

0

Coś takiego:

public boolean hasConnection(final Context context){
    ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNW = cm.getActiveNetworkInfo();
    if (activeNW != null && activeNW.isConnected())
    {
        return true;
    }
    return false;
}

A w głównej części programu:

if(hasConnection(this)) {
    Toast.makeText(this, "Active networks OK ", Toast.LENGTH_LONG).show();
    getAccountData(token, tel);
}
else  Toast.makeText(this, "No active networks... ", Toast.LENGTH_LONG).show();

0

Działa to również w systemie Android 10. Zwróci wartość true, jeśli zostanie podłączony do Internetu, w przeciwnym razie zwróci wartość false.

private fun isOnline(): Boolean {
        val connectivityManager =
                getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val capabilities =
                connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
        if (capabilities != null) {
            when {
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_CELLULAR")
                    return true
                }
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_WIFI")
                    return true
                }
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_ETHERNET")
                    return true
                }
            }
        }
        return false
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.