Ermitteln Sie, ob das Android-Gerät über eine Internetverbindung verfügt

138

Ich muss feststellen, ob mein Gerät über eine Internetverbindung verfügt oder nicht. Ich habe viele Antworten gefunden wie:

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

(Entnommen aus Erkennen, ob unter Android eine Internetverbindung verfügbar ist .)

Dies ist jedoch nicht richtig. Wenn ich beispielsweise mit einem drahtlosen Netzwerk verbunden bin , das keinen Internetzugang hat , gibt diese Methode true zurück. Gibt es eine Möglichkeit, festzustellen, ob das Gerät über eine Internetverbindung verfügt und nicht, ob es nur verbunden ist? zu etwas?

Buda Gavril
quelle
Hey, du kannst auch mit [diesem] [1] gehen. Das könnte helfen! [1]: stackoverflow.com/questions/4238921/…
akshay
Der isNetworkConnectedFunktionsbaustein enthält für alle veralteten Code Build.VERSION.SDK_INT >= Build.VERSION_CODES.M. Eine ausführlichere Diskussion zu diesem Thema und zur Behebung finden Sie hier stackoverflow.com/questions/53532406/…
Basti Vagabond

Antworten:

182

Du hast recht. Der von Ihnen angegebene Code prüft nur, ob eine Netzwerkverbindung besteht. Der beste Weg, um zu überprüfen, ob eine aktive Internetverbindung besteht, besteht darin, über http eine Verbindung zu einem bekannten Server herzustellen.

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

Natürlich können Sie die ersetzen http://www.google.com URL durch jeden anderen Server Sie eine Verbindung herstellen möchten, oder ein Server, von dem Sie wissen, dass er eine gute Betriebszeit hat.

Wie Tony Cho auch in diesem Kommentar unten betonteStellen Sie sicher, dass Sie diesen Code nicht im Hauptthread ausführen, da hat. Andernfalls wird eine NetworkOnMainThread-Ausnahme (in Android 3.0 oder höher) angezeigt. Verwenden Sie stattdessen eine AsyncTask oder Runnable.

Wenn Sie google.com verwenden möchten, sollten Sie sich die Modifikation von Jeshurun ​​ansehen. In seiner Antwort hat er meinen Code geändert und ihn ein bisschen effizienter gemacht. Wenn Sie eine Verbindung zu herstellen

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

und überprüfen Sie dann den Antwortcode für 204

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

Dann müssen Sie nicht zuerst die gesamte Google-Startseite abrufen.

THelper
quelle
9
@varunbhardwaj Sie können einfach eine andere Website verwenden (z. B. baidu.com, wenn Sie Ihre App in China bereitstellen ), oder Sie können eine zweite Website ausprobieren, wenn die erste nicht sicherstellt, dass keine Verbindung besteht.
THelper
2
Ich +1 Ihre Antwort und weiß, wie man sie in meiner App verwendet, aber es gibt einen großen Eckfall der Abhängigkeit von einer Website und meine Frage bleibt immer noch unbeantwortet. Trotzdem eine gute Lösung.
Varun Bhardwaj
2
@blackcrow Hängt davon ab, wie lange Sie / die Benutzer bereit sind zu warten. Persönlich halte ich 1000 ms für die Untergrenze, 6000 ms für den Durchschnitt und 15000 ms lang. Wenn die Prüfung jedoch im Hintergrund ausgeführt wird und der Benutzer nicht darauf wartet, können Sie viel längere Zeitüberschreitungen verwenden.
THelper
1
@varunbhardwaj Es sollte eine URI geben, die Sie von Ihren Webdiensten aus aufrufen können. Das erste, was wir beim Start unserer App anfordern, ist eine Bootstrap-Datei, die verschiedene Konfigurationsinformationen enthält, mit denen wir verschiedene Parameter serverseitig ändern können. So etwas kann verwendet werden.
Steve
11
Dies sollte sich auch in einem Hintergrund-Thread befinden (während das Überprüfen des ConnectivityManagernicht erforderlich ist). Andernfalls erhalten Sie auf Android 4.x + -Geräten eine NetworkOnMainThreadAusnahme.
Anthony Chuinard
90

Ich habe die Antwort von THelper leicht geändert, um einen bekannten Hack zu verwenden, den Android bereits verwendet, um zu überprüfen, ob das verbundene WiFi-Netzwerk über einen Internetzugang verfügt. Dies ist viel effizienter als das Abrufen der gesamten Google-Startseite. Weitere Informationen finden Sie hier und hier .

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
quelle
1
Hallo, ist es in Ordnung, diese Vorgehensweise in aktuellen Apps zu verwenden?
Slava Fomin II
Ist dies bei der Implementierung in unserer aktuellen App effizient?
Therealprashant
5
Es wäre viel effizienter als die Methode in der obigen Antwort. Das Aufrufen der Google-Startseite ist sehr ineffizient, insbesondere wenn sie ein Doodle enthalten.
Jeshurun
1
Die als richtig überprüfte Antwort sollte damit aktualisiert werden, da dies die Antwort verbessert. Gut gemacht Mann, danke
Hugo
3
Sie können g.cn/generate_204 anstelle von clients3.google.com/generate_204 verwenden, wenn Sie die Konnektivität auch in China testen möchten
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;
}

Geben Sie true zurück, wenn das Internet tatsächlich verfügbar ist

Stellen Sie sicher, dass Sie diese beiden Berechtigungen haben

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

Wenn http aufgrund der neuen Android-Sicherheit nicht funktioniert, erlauben sie derzeit keine Nur-Text-Kommunikation. vorerst nur um es zu umgehen.

android: usedCleartextTraffic = "true"

Bilal Shahid
quelle
Dies ist die beste und vollständigste Antwort: Es ist die kürzeste Art, Dinge zu tun (ein Ping greift nicht auf die gesamte Website zu), es läuft unabhängig von Ihrer Verbindung und es läuft in seinem gewonnenen Prozess, so dass es gut mit Android-Versionen funktioniert .
MacD
Was meinst du ? Hier ist ein weiterer Ausschnitt, den ich in einem aktuellen Projekt checkInternet verwende
Bilal Shahid
Was er meinte ist, wird dieser Aufruf die Benutzeroberfläche blockieren und er muss diesen Aufruf im Thread tätigen?
Amit Hooda
2
Dies funktioniert bei mir nicht ... Auslöser: android.os.NetworkOnMainThreadException bei android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork (StrictMode.java:1273) bei java.net.InetAddress.lookupHostByName (InetAddress.java:431) at
Maryadi Poipo
@HyosokaPoipo Sie sollten dies nicht im Haupt-Thread aufrufen. Verwenden Sie einen separaten Thread oder AsyncTask.
Pramesh Bajracharya
14

Wenn Sie auf Lollipop oder höher abzielen, können Sie die neue NetworkCapabilities-Klasse verwenden, z.

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
quelle
1
connectivityManager.getActiveNetwork();erfordert API lvl23, die Marshmallow und nicht Lollipop ist.
Saenic
Sollten wir auch nach Capabilities.hasCapability (NetworkCapabilities.NET_CAPABILITY_INTERNET) suchen?
Alex
Alex capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)schien den Trick für mich zu tun!
Rstojano
6

Sie müssen nicht unbedingt eine vollständige HTTP-Verbindung herstellen. Sie können versuchen, einfach eine TCP-Verbindung zu einem bekannten Host herzustellen. Wenn dies erfolgreich ist, verfügen Sie über eine Internetverbindung.

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

Dann erkundigen Sie sich einfach bei:

boolean online = hostAvailable("www.google.com", 80);
Xiv
quelle
Ist Port 80 ein sicherer Port?
Ralphgabb
Solange es einen HTTP-Server
hostet
Sollte dies beispielsweise in einer AsyncTask verwendet oder nur in der onCreate-Methode der MainActivity aufgerufen werden?
AlexioVay
@Vay alles, was netzwerkbezogen ist, sollte nicht auf dem Haupt- / UI-Thread ausgeführt werden. Also ja, dies sollte in einemAsyncTask
winklerrr
6

Basierend auf den akzeptierten Antworten habe ich diese Klasse mit einem Listener erstellt, damit Sie sie im Hauptthread verwenden können:

Zuerst : InterntCheck-Klasse, die im Hintergrund nach Internetverbindungen sucht und dann eine Listener-Methode mit dem Ergebnis aufruft.

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

}

Zweitens : Instanziieren Sie eine Instanz der Klasse im Hauptthread und warten Sie auf die Antwort (wenn Sie mit Firebase API für Android gearbeitet haben, bevor Ihnen dies bekannt sein sollte!).

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

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

In der onComplete-Methode erhalten Sie nun, ob das Gerät mit dem Internet verbunden ist oder nicht.

Aya
quelle
3

Probier diese

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

Sie müssen Ihrer Manifestdatei die folgende Berechtigung hinzufügen:

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

Dann ruf so an:

if((new ConnectionDetector(MyService.this)).isConnectingToInternet()){
    Log.d("internet status","Internet Access");
}else{
    Log.d("internet status","no Internet Access");
}
Attaullah
quelle
Überprüfen Sie diesen Beitrag stackoverflow.com/questions/36233507/…
Milan Gajera
Dieser Schwule verwendet try catch, daher wird der Fehler nicht angezeigt. Fügen Sie zuerst die Internet-Berechtigung hinzu und versuchen Sie dies dann. seine Arbeit gut
Attaullah
Lassen Sie mich Ihnen sagen, wie ich diese Methode in meiner Aktivität genannt habe?
Milan Gajera
Ich habe versucht, Sie zu posten und ich habe einen Fehler bekommen, den ich in meinem Blog
gepostet
1

Sie können dies mit der ConnectivityManagerAPI für Android tun . Hier können Sie überprüfen, ob Sie mit dem Internet verbunden sind und mit welcher Art von Internetverbindung Sie verbunden sind. Grundsätzlich gemessen oder nicht gemessen.

So überprüfen Sie die Internetverbindung.

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

Dokumentationslink: https://developer.android.com/training/monitoring-device-state/connectivity-status-type

Felix Favor Chinemerem
quelle
Wie überprüfen Sie, ob die mobilen Daten aufgebraucht sind? Dies gibt true zurück, auch wenn mobile Daten verbunden sind und kein Datenguthaben mehr auf dem Konto vorhanden ist.
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;
}

Hoffe, der obige Code hilft Ihnen, stellen Sie auch sicher, dass Sie Internet-Erlaubnis in Ihrer App haben.

RaghavPai
quelle
0

Der neueste Weg, dies aus der Dokumentation zu tun, besteht darin ConnectivityManager, das aktive Netzwerk abzufragen und festzustellen, ob es über eine Internetverbindung verfügt.

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

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

Fügen Sie Ihrer AndroidManifest.xml-Datei diese beiden Berechtigungen hinzu:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Dynamo
quelle
1
Funktioniert nicht :( Wie @Buda Gavril sagt, wenn ich mit einem drahtlosen Netzwerk verbunden bin, das keinen Internetzugang hat, gibt diese Methode immer noch true zurück. Test auf Xiaomi 4, Android 6.0.1.
DysaniazzZ
0

Überprüfen Sie den WLAN-Typ im Konnektivitätsmanager:

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

In der Android-Dokumentation wird 'TYPE_WIFI' als 'WIFI-Datenverbindung' beschrieben. Geräte unterstützen möglicherweise mehrere. '

Vasmos
quelle
0

Eine gute Lösung, um zu überprüfen, ob das aktive Netzwerk über eine Internetverbindung verfügt:

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;
}
Seltener Serban
quelle
0

Sie können ConnectivityManager verwenden.

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

    }

Überprüfen Sie dies und das

Zeni
quelle
0

Verwenden Sie die folgende Klasse , die auf die letzte API-Ebene aktualisiert wurde: 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
quelle