Détecter si l'appareil Android dispose d'une connexion Internet

138

J'ai besoin de savoir si mon appareil est connecté à Internet ou non. J'ai trouvé de nombreuses réponses comme:

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

(Pris à partir de Détecter si une connexion Internet est disponible sur Android .)

Mais ce n'est pas correct, par exemple si je suis connecté à un réseau sans fil qui n'a pas d'accès Internet , cette méthode retournera vrai… Y a-t-il un moyen de savoir si l'appareil a une connexion Internet et non s'il est uniquement connecté de quelque chose?

Buda Gavril
la source
Hé, vous pouvez aussi utiliser [ceci] [1]. Cela pourrait aider! [1]: stackoverflow.com/questions/4238921/…
akshay
Le isNetworkConnectedbloc fonctionnel contient du code obsolète pour tous Build.VERSION.SDK_INT >= Build.VERSION_CODES.M. Une discussion plus approfondie sur le sujet et comment y remédier peut être trouvée ici stackoverflow.com/questions/53532406/…
Basti Vagabond

Réponses:

182

Vous avez raison. Le code que vous avez fourni vérifie uniquement s'il existe une connexion réseau. La meilleure façon de vérifier s'il existe une connexion Internet active est d'essayer de vous connecter à un serveur connu via 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;
}

Bien sûr, vous pouvez remplacer l' http://www.google.comURL de tout autre serveur auquel vous souhaitez vous connecter, ou d'un serveur dont vous savez qu'il a une bonne disponibilité.

Comme Tony Cho l'a également souligné dans ce commentaire ci - dessous , assurez-vous de ne pas exécuter ce code sur le thread principal, sinon vous obtiendrez une exception NetworkOnMainThread (sous Android 3.0 ou version ultérieure). Utilisez plutôt une AsyncTask ou Runnable.

Si vous souhaitez utiliser google.com, vous devriez regarder la modification de Jeshurun. Dans sa réponse, il a modifié mon code et l'a rendu un peu plus efficace. Si vous vous connectez à

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

puis vérifiez le code de réponse pour 204

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

alors vous n'avez pas besoin de récupérer la page d'accueil entière de Google en premier.

THelper
la source
9
@varunbhardwaj, vous pouvez simplement prendre un site Web différent (par exemple baidu.com lors du déploiement de votre application en Chine), ou vous pouvez essayer un deuxième site si le premier ne parvient pas à vous assurer qu'il n'y a pas de connexion.
THelper
2
Je attribue +1 à votre réponse et je sais l'utiliser dans mon application, mais il y a un gros cas de dépendance à certains sites Web et ma question reste toujours sans réponse. de toute façon une excellente solution de contournement merci.
varun bhardwaj
2
@blackcrow Dépend de combien de temps vous / les utilisateurs êtes prêts à attendre. Personnellement, je considère que 1000 ms est la limite inférieure, 6000 ms en moyenne et 15000 ms de long. Mais si la vérification s'exécute en arrière-plan et que l'utilisateur ne l'attend pas, vous pouvez utiliser des délais beaucoup plus longs.
THelper
1
@varunbhardwaj Il devrait y avoir des URI que vous pouvez atteindre à partir de vos services Web. La première chose que nous demandons au démarrage de notre application est un fichier d'amorçage contenant diverses informations de configuration, qui nous permet de modifier divers paramètres côté serveur. Quelque chose comme ça peut être utilisé.
Steve
11
Cela devrait également être sur un thread d'arrière-plan (alors que la vérification de ConnectivityManagerne l'exige pas). Sinon, sur les appareils Android 4.x +, vous obtiendrez une NetworkOnMainThreadexception.
Anthony Chuinard
90

J'ai légèrement modifié la réponse de THelper, pour utiliser un hack connu qu'Android utilise déjà pour vérifier si le réseau WiFi connecté a accès à Internet. C'est beaucoup plus efficace que de saisir toute la page d'accueil de Google. Voir ici et ici pour plus d'informations.

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
la source
1
Bonjour, est-il acceptable d'utiliser cette pratique dans les applications actuelles?
Slava Fomin II
Est-ce efficace pour l'implémentation dans notre application actuelle?
therealprashant
5
Ce serait bien plus efficace que la méthode décrite ci-dessus. Saisir la page d'accueil de Google est très inefficace, surtout s'il y a un doodle dessus.
Jeshurun
1
La réponse vérifiée comme correcte doit être mise à jour avec ceci car cela améliore la réponse. Bien joué, merci
Hugo le
3
Vous pouvez également utiliser g.cn/generate_204 au lieu de clients3.google.com/generate_204 si vous souhaitez également tester la connectivité en Chine
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;
}

renvoie true si Internet est réellement disponible

Assurez-vous d'avoir ces deux autorisations

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

si http ne fonctionne pas, c'est à cause de la nouvelle sécurité Android, ils n'autorisent pas la communication en texte brut maintenant. pour l'instant juste pour le contourner.

android: usesCleartextTraffic = "true"

Bilal Shahid
la source
C'est la meilleure réponse, la plus complète: c'est le moyen le plus court de faire les choses (un ping n'accède pas à l'ensemble du site Web), il fonctionne indépendamment de la connexion que vous avez et il fonctionne dans son processus gagné, donc il joue bien avec les versions Android .
MacD
Que voulez-vous dire ? voici un autre extrait que j'utilise
Bilal Shahid
ce qu'il voulait dire, c'est que cet appel bloquera l'interface utilisateur et qu'il doit faire cet appel dans le fil?
Amit Hooda
2
Cela ne fonctionne pas pour moi ... Causé par: android.os.NetworkOnMainThreadException à android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork (StrictMode.java:1273) à java.net.InetAddress.lookupHostByName (InetAddress.java:431) at
Maryadi Poipo
@HyosokaPoipo vous ne devez pas appeler cela sur le thread principal. Utilisez un thread distinct ou AsyncTask.
Pramesh Bajracharya
14

Si vous ciblez Lollipop ou une version supérieure, il est possible d'utiliser la nouvelle classe NetworkCapabilities, c'est-à-dire:

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
la source
1
connectivityManager.getActiveNetwork();nécessite l'API lvl23 qui est Marshmallow et non Lollipop.
Saenic
Devrions-nous également vérifier les capacités.hasCapability (NetworkCapabilities.NET_CAPABILITY_INTERNET)?
Alex
Alex capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)semblait faire l'affaire pour moi!
rstojano
6

Vous n'avez pas nécessairement besoin d'établir une connexion HTTP complète. Vous pouvez simplement essayer d'ouvrir une connexion TCP à un hôte connu et si cela réussit, vous disposez d'une connectivité Internet.

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;
  }
}

Ensuite, vérifiez simplement avec:

boolean online = hostAvailable("www.google.com", 80);
Xiv
la source
le port 80 est-il un port sûr à utiliser?
ralphgabb
Tant qu'il héberge un serveur HTTP, il devrait accepter une connexion TCP sur le port 80.
Xiv
Doit-il être utilisé dans une AsyncTask ou simplement appelé dans la méthode onCreate de MainActivity par exemple?
AlexioVay
@Vay tout ce qui est lié au réseau ne doit pas fonctionner sur le thread principal / ui. Donc oui, cela devrait être utilisé dans unAsyncTask
winklerrr
6

Sur la base des réponses acceptées, j'ai construit cette classe avec un écouteur afin que vous puissiez l'utiliser dans le fil principal:

Premièrement : la classe InterntCheck qui vérifie la connexion Internet en arrière-plan, puis appelle une méthode d'écoute avec le résultat.

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);
    }

}

Deuxièmement : instanciez une instance de la classe dans le thread principal et attendez la réponse (si vous avez déjà travaillé avec Firebase api pour Android, cela devrait vous être familier!).

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

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

Maintenant, dans la méthode onComplete, vous saurez si l'appareil est connecté à Internet ou non.

Aya
la source
3

essaye celui-là

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;
    }
}

vous devrez ajouter l'autorisation suivante à votre fichier manifeste:

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

Puis appelez comme ça:

if((new ConnectionDetector(MyService.this)).isConnectingToInternet()){
    Log.d("internet status","Internet Access");
}else{
    Log.d("internet status","no Internet Access");
}
Attaullah
la source
Consultez ce message stackoverflow.com/questions/36233507/…
Milan Gajera
ce gay utilise try catch donc l'erreur n'est pas affichée s'il vous plaît d'abord ajouter l'autorisation Internet puis essayez ceci. son travail bien
Attaullah
Laissez-moi vous dire comment j'ai appelé cette méthode dans mon activité?
Milan Gajera
J'ai essayé de vous publier et j'ai eu une erreur qui m'a
envoyé
1

Vous pouvez le faire en utilisant l' ConnectivityManagerAPI pour Android. Il vous permet de vérifier si vous êtes connecté à Internet et le type de connexion Internet auquel vous êtes connecté. Fondamentalement, mesuré ou non.

Pour vérifier la connexion Internet.

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

Lien de documentation: https://developer.android.com/training/monitoring-device-state/connectivity-status-type

Felix Favor Chinemerem
la source
Comment vérifier si les données mobiles sont épuisées? Cela renvoie vrai même si les données mobiles sont connectées et qu'il n'y a pas de solde de données restant sur le compte.
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;
}

J'espère que le code ci-dessus vous aidera, assurez-vous également que vous avez l'autorisation Internet dans votre application.

RaghavPai
la source
0

La dernière façon de le faire à partir de la documentation consiste à utiliser le ConnectivityManagerpour interroger le réseau actif et déterminer s'il dispose d'une connectivité Internet.

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

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

Ajoutez ces deux autorisations à votre fichier AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
dynamo
la source
1
Ne fonctionne pas: (Comme le dit @Buda Gavril, si je suis connecté à un réseau sans fil qui n'a pas d'accès Internet, cette méthode retournera toujours vrai. Test sur Xiaomi 4, Android 6.0.1.
DysaniazzZ
0

Vérifiez le type de wifi dans le gestionnaire de connectivité:

   //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);

La documentation Android décrit «TYPE_WIFI» comme «une connexion de données WIFI. Les appareils peuvent en prendre en charge plusieurs. »

vasmos
la source
0

Une belle solution pour vérifier si le réseau actif dispose d'une connexion Internet:

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;
}
Serban rare
la source
0

Vous pouvez utiliser 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

    }

Vérifiez ceci et cela

Zeni
la source
0

Utilisez la classe suivante , mise à jour au dernier niveau d'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
la source