Wykryj, czy urządzenie z Androidem ma połączenie z Internetem

138

Muszę sprawdzić, czy moje urządzenie ma połączenie z Internetem, czy nie. Znalazłem wiele odpowiedzi, takich jak:

private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager 
         = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null;
}

(Zaczerpnięte z opcji Wykryj, czy w systemie Android jest dostępne połączenie internetowe ).

Ale to nie w porządku, na przykład jeśli jestem podłączony do sieci bezprzewodowej, która nie ma dostępu do Internetu , ta metoda zwróci prawdę… Czy istnieje sposób, aby sprawdzić, czy urządzenie ma połączenie z Internetem, a nie, czy jest podłączone tylko do czegoś?

Buda Gavril
źródło
Hej, możesz też iść z [tym] [1]. To może pomóc! [1]: stackoverflow.com/questions/4238921/…
akshay
isNetworkConnectedBlok zawiera kod przestarzałej dla wszystkich Build.VERSION.SDK_INT >= Build.VERSION_CODES.M. Bardziej dogłębną dyskusję na ten temat i jak to naprawić można znaleźć tutaj stackoverflow.com/questions/53532406/…
Basti Vagabond

Odpowiedzi:

182

Masz rację. Podany kod sprawdza tylko, czy istnieje połączenie sieciowe. Najlepszym sposobem sprawdzenia, czy istnieje aktywne połączenie internetowe, jest próba połączenia się ze znanym serwerem za pośrednictwem protokołu http.

public static boolean hasActiveInternetConnection(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
            urlc.setRequestProperty("User-Agent", "Test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 200);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(LOG_TAG, "No network available!");
    }
    return false;
}

Oczywiście możesz zastąpić http://www.google.comadres URL dowolnego innego serwera, z którym chcesz się połączyć, lub serwera, o którym wiesz, że ma dobry czas pracy.

Jak Tony Cho wskazał również w tym komentarzu poniżej , upewnij się, że nie uruchamiasz tego kodu w głównym wątku, w przeciwnym razie otrzymasz wyjątek NetworkOnMainThread (w systemie Android 3.0 lub nowszym). Zamiast tego użyj AsyncTask lub Runnable.

Jeśli chcesz korzystać z google.com, powinieneś spojrzeć na modyfikację Jeshurun. W swojej odpowiedzi zmodyfikował mój kod i uczynił go nieco bardziej wydajnym. Jeśli łączysz się z

HttpURLConnection urlc = (HttpURLConnection) 
            (new URL("http://clients3.google.com/generate_204")
            .openConnection());

a następnie sprawdź kod odpowiedzi dla 204

return (urlc.getResponseCode() == 204 && urlc.getContentLength() == 0);

wtedy nie musisz najpierw pobierać całej strony głównej Google.

THelper
źródło
9
@varunbhardwaj możesz po prostu wybrać inną witrynę (np. baidu.com podczas wdrażania aplikacji w Chinach) lub możesz wypróbować drugą witrynę, jeśli pierwsza nie upewni się, że nie ma połączenia.
THelper
2
Daję Ci +1 Twojej odpowiedzi i wiem, że używam jej w mojej aplikacji, ale istnieje duży przypadek zależności od jakiejś strony internetowej, a moje pytanie nadal pozostaje bez odpowiedzi. w każdym razie świetne obejście, dzięki.
varun bhardwaj
2
@blackcrow Zależy od tego, jak długo ty / użytkownicy chcecie czekać. Osobiście uważam 1000ms za dolną granicę, 6000ms średnio i 15000ms długo. Ale jeśli sprawdzanie działa w tle, a użytkownik nie czeka na to, możesz użyć znacznie dłuższych limitów czasu.
THelper
1
@varunbhardwaj Powinien istnieć identyfikator URI, który można uzyskać z usług internetowych. Pierwszą rzeczą, o którą prosimy podczas uruchamiania naszej aplikacji, jest plik bootstrap zawierający różne informacje konfiguracyjne, które pozwalają nam zmieniać różne parametry po stronie serwera. Coś takiego można użyć.
Steve,
11
Powinno to również znajdować się w wątku w tle (chociaż sprawdzenie tego ConnectivityManagernie wymaga). W przeciwnym razie na urządzeniach z Androidem 4.x + pojawi się NetworkOnMainThreadwyjątek.
Anthony Chuinard
90

Zmodyfikowałem nieco odpowiedź THelpera, aby użyć znanego hacka, którego używa już Android, do sprawdzenia, czy podłączona sieć Wi-Fi ma dostęp do Internetu. Jest to o wiele bardziej wydajne niż przechwytywanie całej strony głównej Google. Zobacz tutaj i tutaj, aby uzyskać więcej informacji.

public static boolean hasInternetAccess(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) 
                (new URL("http://clients3.google.com/generate_204")
                .openConnection());
            urlc.setRequestProperty("User-Agent", "Android");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
        } catch (IOException e) {
            Log.e(TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(TAG, "No network available!");
    }
    return false;
}
Jeshurun
źródło
1
Witam, czy mogę używać tej praktyki w obecnych aplikacjach?
Slava Fomin II
Czy jest to wydajne w implementacji w naszej obecnej aplikacji?
therealprashant
5
Byłoby to o wiele bardziej wydajne niż metoda w powyższej odpowiedzi. Przechwytywanie strony głównej Google jest bardzo nieefektywne, zwłaszcza jeśli zdarzy się, że mają na niej doodle.
Jeshurun
1
Zaznaczona odpowiedź jako poprawna powinna zostać zaktualizowana o to, ponieważ poprawia odpowiedź. Dobra robota, dzięki
Hugo,
3
Możesz użyć g.cn/generate_204 zamiast client3.google.com/generate_204, jeśli chcesz przetestować łączność również w Chinach
breez
18
public boolean isInternetWorking() {
    boolean success = false;
    try {
        URL url = new URL("https://google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(10000);
        connection.connect();
        success = connection.getResponseCode() == 200;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return success;
}

zwraca wartość true, jeśli internet jest rzeczywiście dostępny

Upewnij się, że masz te dwa uprawnienia

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

jeśli http nie działa, to z powodu nowych zabezpieczeń Androida, nie pozwalają teraz na komunikację zwykłym tekstem. na razie tylko po to, żeby to ominąć.

android: usesCleartextTraffic = "true"

Bilal Shahid
źródło
To najlepsza, najbardziej kompletna odpowiedź: to najkrótszy sposób działania (ping nie ma dostępu do całej witryny), działa niezależnie od tego, jakie masz połączenie i działa w wygranym procesie, więc działa dobrze z wersjami Androida .
MacD
co masz na myśli ? oto kolejny fragment, którego używam w bieżącym projekcie checkInternet
Bilal Shahid
miał na myśli to, czy to wywołanie zablokuje interfejs użytkownika i musi wykonać to wywołanie w wątku?
Amit Hooda
2
To nie działa dla mnie ... Przyczyna: android.os.NetworkOnMainThreadException w android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork (StrictMode.java:1273) w java.net.InetAddress.lookupHostByName (InetAddress.java:431) at
Maryadi Poipo
@HyosokaPoipo nie powinieneś wywoływać tego w głównym wątku. Użyj osobnego wątku lub AsyncTask.
Pramesh Bajracharya
14

Jeśli celujesz w Lollipop lub nowszy, możesz użyć nowej klasy NetworkCapabilities, tj .:

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

    final Network network = connectivityManager.getActiveNetwork();
    final NetworkCapabilities capabilities = connectivityManager
            .getNetworkCapabilities(network);

    return capabilities != null
            && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}
Johan
źródło
1
connectivityManager.getActiveNetwork();wymaga API lvl23, którym jest Marshmallow, a nie Lollipop.
Saenic
Czy powinniśmy również sprawdzić, czy nie ma możliwości.hasCapability (NetworkCapabilities.NET_CAPABILITY_INTERNET)?
Alex
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)Wydawało się, że Alex załatwił sprawę za mnie!
rstojano
6

Nie musisz koniecznie tworzyć pełnego połączenia HTTP. Możesz po prostu spróbować otworzyć połączenie TCP ze znanym hostem, a jeśli się powiedzie, masz połączenie z Internetem.

public boolean hostAvailable(String host, int port) {
  try (Socket socket = new Socket()) {
    socket.connect(new InetSocketAddress(host, port), 2000);
    return true;
  } catch (IOException e) {
    // Either we have a timeout or unreachable host or failed DNS lookup
    System.out.println(e);
    return false;
  }
}

Następnie po prostu sprawdź:

boolean online = hostAvailable("www.google.com", 80);
Xiv
źródło
czy port 80 jest bezpiecznym portem w użyciu?
ralphgabb
Dopóki hostuje serwer HTTP, powinien akceptować połączenie TCP na porcie 80.
Xiv
Czy powinno to być używane wewnątrz AsyncTask lub po prostu wywoływane w metodzie onCreate MainActivity na przykład?
AlexioVay
@Vay wszystko, co jest związane z siecią, nie powinno działać w wątku głównym / ui. Więc tak, to powinno być używane wewnątrzAsyncTask
winklerrr
6

Na podstawie zaakceptowanych odpowiedzi zbudowałem tę klasę ze słuchaczem, abyś mógł jej używać w głównym wątku:

Najpierw : klasa InterntCheck, która w tle sprawdza połączenie internetowe, a następnie wywołuje metodę listenera z wynikiem.

public class InternetCheck extends AsyncTask<Void, Void, Void> {


    private Activity activity;
    private InternetCheckListener listener;

    public InternetCheck(Activity x){

        activity= x;

    }

    @Override
    protected Void doInBackground(Void... params) {


        boolean b = hasInternetAccess();
        listener.onComplete(b);

        return null;
    }


    public void isInternetConnectionAvailable(InternetCheckListener x){
        listener=x;
        execute();
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager) activity.getSystemService(CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null;
    }
    private boolean hasInternetAccess() {
        if (isNetworkAvailable()) {
            try {
                HttpURLConnection urlc = (HttpURLConnection) (new URL("http://clients3.google.com/generate_204").openConnection());
                urlc.setRequestProperty("User-Agent", "Android");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(1500);
                urlc.connect();
                return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.d("TAG", "No network available!");
        }
        return false;
    }

    public interface InternetCheckListener{
        void onComplete(boolean connected);
    }

}

Po drugie : utwórz instancję klasy w głównym wątku i poczekaj na odpowiedź (jeśli pracowałeś z interfejsem Firebase dla Androida, zanim będzie Ci to znane!).

new InternetCheck(activity).isInternetConnectionAvailable(new InternetCheck.InternetCheckListener() {

        @Override
        public void onComplete(boolean connected) {
           //proceed!
        }
    });

Teraz w metodzie onComplete dowiesz się, czy urządzenie jest podłączone do Internetu, czy nie.

Aya
źródło
3

Spróbuj tego

public class ConnectionDetector {
    private Context _context;

    public ConnectionDetector(Context context) {
        this._context = context;
    }

    public boolean isConnectingToInternet() {
        if (networkConnectivity()) {
            try {
                HttpURLConnection urlc = (HttpURLConnection) (new URL(
                        "http://www.google.com").openConnection());
                urlc.setRequestProperty("User-Agent", "Test");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(3000);
                urlc.setReadTimeout(4000);
                urlc.connect();
                // networkcode2 = urlc.getResponseCode();
                return (urlc.getResponseCode() == 200);
            } catch (IOException e) {
                return (false);
            }
        } else
            return false;

    }

    private boolean networkConnectivity() {
        ConnectivityManager cm = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            return true;
        }
        return false;
    }
}

musisz dodać następujące uprawnienia do swojego pliku manifestu:

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

Następnie zadzwoń w ten sposób:

if((new ConnectionDetector(MyService.this)).isConnectingToInternet()){
    Log.d("internet status","Internet Access");
}else{
    Log.d("internet status","no Internet Access");
}
Attaullah
źródło
sprawdź ten post stackoverflow.com/questions/36233507/…
Milan Gajera
ten wesoły używa try catch, dlatego błąd nie jest wyświetlany, najpierw dodaj pozwolenie na Internet, a następnie spróbuj. jego praca jest dobra
Attaullah
Powiem ci, jak nazwałem tę metodę w mojej działalności?
Milan Gajera
Próbowałem z tobą
pisać
1

Możesz to zrobić za pomocą ConnectivityManagerAPI dla Androida. Pozwala sprawdzić, czy masz połączenie z Internetem i typ połączenia internetowego, z którym jesteś połączony. Zasadniczo mierzone lub nie mierzone.

Aby sprawdzić połączenie internetowe.

ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();

Link do dokumentacji: https://developer.android.com/training/monitoring-device-state/connectivity-status-type

Felix Favor Chinemerem
źródło
Jak sprawdzić, czy dane mobilne się wyczerpały? Zwraca to prawdę, nawet jeśli dane mobilne są podłączone i na koncie nie ma salda danych.
user2672052
0
private static NetworkUtil mInstance;
private volatile boolean mIsOnline;

private NetworkUtil() {
    ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
    exec.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            boolean reachable = false;
            try {
                Process process = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
                int returnVal = process.waitFor();
                reachable = (returnVal==0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            mIsOnline = reachable;
        }
    }, 0, 5, TimeUnit.SECONDS);
}

public static NetworkUtil getInstance() {
    if (mInstance == null) {
        synchronized (NetworkUtil.class) {
            if (mInstance == null) {
                mInstance = new NetworkUtil();
            }
        }
    }
    return mInstance;
}

public boolean isOnline() {
    return mIsOnline;
}

Mam nadzieję, że powyższy kod ci pomoże, upewnij się również, że masz uprawnienia do Internetu w swojej aplikacji.

RaghavPai
źródło
0

Najnowszym sposobem na to z dokumentacji jest użycie ConnectivityManagerzapytania do aktywnej sieci i określenia, czy ma ona połączenie z Internetem.

public boolean hasInternetConnectivity() {
    ConnectivityManager cm =
        (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return (activeNetwork != null &&
                      activeNetwork.isConnectedOrConnecting());
}

Dodaj te dwa uprawnienia do pliku AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
dynamo
źródło
1
Nie działa :( Jak mówi @Buda Gavril, jeśli jestem podłączony do sieci bezprzewodowej, która nie ma dostępu do Internetu, ta metoda nadal będzie
działać
0

Sprawdź typ wifi w menedżerze łączności:

   //check network connection
    ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    boolean hasNetworkConnection = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    System.out.println("Connection ? : " + hasNetworkConnection);
    //check wifi
    boolean hasWifiConnection = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
    System.out.println("Wifi ? : " + hasWifiConnection);

Dokumentacja systemu Android opisuje „TYPE_WIFI” jako „połączenie danych WIFI. Urządzenia mogą obsługiwać więcej niż jeden ”.

vasmos
źródło
0

Fajne rozwiązanie, aby sprawdzić, czy aktywna sieć ma połączenie z Internetem:

public boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager != null) {
        Network network = connectivityManager.getActiveNetwork();
        NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
        return networkCapabilities != null && networkCapabilities
                .hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    }
    return false;
}
Rzadki Serban
źródło
0

Możesz użyć ConnectivityManager.

val cm = getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
            val dialogBuilder = AlertDialog.Builder(this)

            if (activeNetwork!=null) // Some network is available
            {
                if (activeNetwork.isConnected) { // Network is connected to internet

    }else{ // Network is NOT connected to internet

    }

Sprawdź to i to

Zeni
źródło
0

Użyj następującej klasy , zaktualizowanej do ostatniego poziomu API: 29.

// License: MIT
// http://opensource.org/licenses/MIT
package net.i2p.android.router.util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.telephony.TelephonyManager;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.concurrent.CancellationException;



/**
 * Check device's network connectivity and speed.
 *
 * @author emil http://stackoverflow.com/users/220710/emil
 * @author str4d
 * @author rodrigo https://stackoverflow.com/users/5520417/rodrigo
 */
public class ConnectivityAndInternetAccessCheck {

    private static ArrayList < String > hosts = new ArrayList < String > () {
        {
            add("google.com");
            add("facebook.com");
            add("apple.com");
            add("amazon.com");
            add("twitter.com");
            add("linkedin.com");
            add("microsoft.com");
        }
    };
    /**
     * Get the network info.
     *
     * @param context the Context.
     * @return the active NetworkInfo.
     */
    private static NetworkInfo getNetworkInfo(Context context) {
        NetworkInfo networkInfo = null;
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            networkInfo = cm.getActiveNetworkInfo();
        }
        return networkInfo;
    }

    /**
     * Gets the info of all networks
     * @param context The context
     * @return an array of @code{{@link NetworkInfo}}
     */
    private static NetworkInfo[] getAllNetworkInfo(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getAllNetworkInfo();
    }

    /**
     * Gives the connectivity manager
     * @param context The context
     * @return the @code{{@link ConnectivityManager}}
     */
    private static ConnectivityManager getConnectivityManager(Context context) {
        return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    /**
     * Check if there is any connectivity at all.
     *
     * @param context the Context.
     * @return true if we are connected to a network, false otherwise.
     */
    public static boolean isConnected(Context context) {
        boolean isConnected = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] networks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: networks) {
                if (network == null) {
                    isConnected = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        isConnected = true;
                        break networksloop;
                    }
                    else {
                        isConnected = false;
                    }
                }
            }

        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo info: networkInfos) {
                // Works on emulator and devices.
                // Note the use of isAvailable() - without this, isConnected() can
                // return true when Wifi is disabled.
                // http://stackoverflow.com/a/2937915
                isConnected = info != null && info.isAvailable() && info.isConnected();
                if (isConnected) {
                    break networkinfosloop;
                }
            }

        }
        return isConnected;
    }

    /**
     * Check if there is any connectivity to a Wifi network.
     *
     * @param context the Context.
     * @return true if we are connected to a Wifi network, false otherwise.
     */
    public static boolean isConnectedWifi(Context context) {
        boolean isConnectedWifi = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] networks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: networks) {
                if (network == null) {
                    isConnectedWifi = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                            isConnectedWifi = true;
                            break networksloop;
                        } else {
                            isConnectedWifi = false;
                        }
                    }
                }

            }


        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo n: networkInfos) {
                isConnectedWifi = n != null && n.isAvailable() && n.isConnected() && n.getType() == ConnectivityManager.TYPE_WIFI;
                if (isConnectedWifi) {
                    break networkinfosloop;
                }

            }
        }
        return isConnectedWifi;
    }

    /**
     * Check if there is any connectivity to a mobile network.
     *
     * @param context the Context.
     * @return true if we are connected to a mobile network, false otherwise.
     */
    public static boolean isConnectedMobile(Context context) {
        boolean isConnectedMobile = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] allNetworks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: allNetworks) {
                if (network == null) {
                    isConnectedMobile = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                            isConnectedMobile = true;
                            break networksloop;
                        } else {
                            isConnectedMobile = false;
                        }
                    }
                }

            }

        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo networkInfo: networkInfos) {
                isConnectedMobile = networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected() && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
                if (isConnectedMobile) {
                    break networkinfosloop;
                }
            }
        }
        return isConnectedMobile;
    }

    /**
     * Check if there is fast connectivity.
     *
     * @param context the Context.
     * @return true if we have "fast" connectivity, false otherwise.
     */
    public static boolean isConnectedFast(Context context) {
        boolean isConnectedFast = false;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkInfosloop:
            for (NetworkInfo networkInfo: networkInfos) {
                isConnectedFast = networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected() && isConnectionFast(networkInfo.getType(), networkInfo.getSubtype());
                if (isConnectedFast) {
                    break networkInfosloop;
                }
            }
        } else {
            throw new UnsupportedOperationException();
        }
        return isConnectedFast;
    }

    /**
     * Check if the connection is fast.
     *
     * @param type the network type.
     * @param subType the network subtype.
     * @return true if the provided type/subtype combination is classified as fast.
     */
    private static boolean isConnectionFast(int type, int subType) {
        if (type == ConnectivityManager.TYPE_WIFI) {
            return true;
        } else if (type == ConnectivityManager.TYPE_MOBILE) {
            switch (subType) {
                case TelephonyManager.NETWORK_TYPE_1xRTT:
                    return false; // ~ 50-100 kbps
                case TelephonyManager.NETWORK_TYPE_CDMA:
                    return false; // ~ 14-64 kbps
                case TelephonyManager.NETWORK_TYPE_EDGE:
                    return false; // ~ 50-100 kbps
                case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    return true; // ~ 400-1000 kbps
                case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    return true; // ~ 600-1400 kbps
                case TelephonyManager.NETWORK_TYPE_GPRS:
                    return false; // ~ 100 kbps
                case TelephonyManager.NETWORK_TYPE_HSDPA:
                    return true; // ~ 2-14 Mbps
                case TelephonyManager.NETWORK_TYPE_HSPA:
                    return true; // ~ 700-1700 kbps
                case TelephonyManager.NETWORK_TYPE_HSUPA:
                    return true; // ~ 1-23 Mbps
                case TelephonyManager.NETWORK_TYPE_UMTS:
                    return true; // ~ 400-7000 kbps
                /*
                 * Above API level 7, make sure to set android:targetSdkVersion
                 * to appropriate level to use these
                 */
                case TelephonyManager.NETWORK_TYPE_EHRPD: // API level 11
                    return true; // ~ 1-2 Mbps
                case TelephonyManager.NETWORK_TYPE_EVDO_B: // API level 9
                    return true; // ~ 5 Mbps
                case TelephonyManager.NETWORK_TYPE_HSPAP: // API level 13
                    return true; // ~ 10-20 Mbps
                case TelephonyManager.NETWORK_TYPE_IDEN: // API level 8
                    return false; // ~25 kbps
                case TelephonyManager.NETWORK_TYPE_LTE: // API level 11
                    return true; // ~ 10+ Mbps
                // Unknown
                case TelephonyManager.NETWORK_TYPE_UNKNOWN:
                default:
                    return false;
            }
        } else {
            return false;
        }
    }

    public ArrayList < String > getHosts() {
        return hosts;
    }

    public void setHosts(ArrayList < String > hosts) {
        this.hosts = hosts;
    }
    //TODO Debug on devices
    /**
     * Checks that Internet is available by pinging DNS servers.
     */
    private static class InternetConnectionCheckAsync extends AsyncTask < Void, Void, Boolean > {

        private Context context;

        /**
         * Creates an instance of this class
         * @param context The context
         */
        public InternetConnectionCheckAsync(Context context) {
            this.setContext(context);
        }

        /**
         * Cancels the activity if the device is not connected to a network.
         */
        @Override
        protected void onPreExecute() {
            if (!ConnectivityAndInternetAccessCheck.isConnected(getContext())) {
                cancel(true);
            }
        }

        /**
         * Tells whether there is Internet access
         * @param voids The list of arguments
         * @return True if Internet can be accessed
         */
        @Override
        protected Boolean doInBackground(Void...voids) {
            return isConnectedToInternet(getContext());
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
        }

        /**
         * The context
         */
        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }
    } //network calls shouldn't be called from main thread otherwise it will throw //NetworkOnMainThreadException

    /**
     * Tells whether Internet is reachable
     * @return true if Internet is reachable, false otherwise
     * @param context The context
     */
    public static boolean isInternetReachable(Context context) {
        try {
            return new InternetConnectionCheckAsync(context).execute().get();
        } catch (CancellationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Tells whether there is Internet connection
     * @param context The context
     * @return @code {true} if there is Internet connection
     */
    private static boolean isConnectedToInternet(Context context) {
        boolean isAvailable = false;
        if (!ConnectivityAndInternetAccessCheck.isConnected(context)) {
            isAvailable = false;
        } else {
            try {
                foreachloop: for (String h: new ConnectivityAndInternetAccessCheck().getHosts()) {
                    if (isHostAvailable(h)) {
                        isAvailable = true;
                        break foreachloop;
                    }
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }

        return isAvailable;

    }

    /**
     * Checks if the host is available
     * @param hostName
     * @return
     * @throws IOException
     */
    private static boolean isHostAvailable(String hostName) throws IOException {
        try (Socket socket = new Socket()) {
            int port = 80;
            InetSocketAddress socketAddress = new InetSocketAddress(hostName, port);
            socket.connect(socketAddress, 3000);

            return true;
        } catch (UnknownHostException unknownHost) {
            return false;
        }
    }
}
Rodrigo
źródło