Rileva se il dispositivo Android ha una connessione Internet


138

Devo dire se il mio dispositivo ha una connessione Internet o meno. Ho trovato molte risposte come:

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

(Tratto da Rileva se è disponibile una connessione Internet su Android .)

Ma questo non è giusto, ad esempio se sono connesso a una rete wireless che non ha accesso a Internet , questo metodo tornerà vero ... C'è un modo per dire se il dispositivo ha una connessione Internet e non se è solo connesso a qualcosa?


Ehi, puoi andare anche con [this] [1]. Questo potrebbe aiutare! [1]: stackoverflow.com/questions/4238921/...
Akshay


Il isNetworkConnectedblocco funzione contiene codice deprecato per tutti Build.VERSION.SDK_INT >= Build.VERSION_CODES.M. Una discussione più approfondita sulla questione e su come risolverla può essere trovata qui stackoverflow.com/questions/53532406/…
Basti Vagabond

Risposte:


182

Hai ragione. Il codice che hai fornito controlla solo se esiste una connessione di rete. Il modo migliore per verificare se esiste una connessione Internet attiva è provare a connettersi a un server noto tramite 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;
}

Ovviamente puoi sostituire l' http://www.google.comURL con qualsiasi altro server a cui vuoi connetterti, o un server che conosci ha un buon tempo di attività.

Come ha sottolineato anche Tony Cho in questo commento , assicurati di non eseguire questo codice sul thread principale, altrimenti otterrai un'eccezione NetworkOnMainThread (in Android 3.0 o versioni successive). Utilizzare invece un AsyncTask o Runnable.

Se vuoi usare google.com dovresti guardare la modifica di Jeshurun. Nella sua risposta ha modificato il mio codice e lo ha reso un po 'più efficiente. Se ti connetti a

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

e quindi controlla il codice di risposta per 204

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

quindi non devi prima recuperare l'intera home page di Google.


9
@varunbhardwaj puoi semplicemente visitare un sito Web diverso (ad esempio baidu.com durante la distribuzione della tua app in Cina), oppure puoi provare un secondo sito se il primo non riesce a verificare che non ci siano connessioni.
THelper

2
Io +1 la tua risposta e so di usarla nella mia app, ma c'è un grosso caso di dipendenza su alcuni siti Web e la mia domanda rimane ancora senza risposta. comunque ottima soluzione grazie.
varun bhardwaj,

2
@blackcrow Dipende da quanto tempo tu / gli utenti siete disposti ad aspettare. Personalmente considero 1000ms come limite inferiore, 6000ms in media e 15000ms in lunghezza. Ma se il controllo è in esecuzione in background e l'utente non lo sta aspettando, è possibile utilizzare timeout molto più lunghi.
THelper

1
@varunbhardwaj Dovrebbero esserci degli URI che puoi colpire dai tuoi servizi web. La prima cosa che richiediamo all'avvio della nostra app è un file bootstrap che contiene varie informazioni di configurazione, che ci consente di modificare vari parametri sul lato server. Qualcosa del genere può essere usato.
Steve

11
Questo dovrebbe anche essere inattivo su un thread in background (mentre il controllo ConnectivityManagernon lo richiede). Altrimenti, sui dispositivi Android 4.x +, otterrai NetworkOnMainThreadun'eccezione.
Anthony Chuinard,

90

Ho modificato leggermente la risposta di THelper, per utilizzare un hack noto che Android già utilizza per verificare se la rete WiFi connessa ha accesso a Internet. Questo è molto più efficiente rispetto all'afferrare l'intera home page di Google. Vedi qui e qui per maggiori informazioni.

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

1
Ciao, è OK usare questa pratica nelle app attuali?
Slava Fomin II

È efficace nell'implementazione nella nostra app attuale?
therealprashant

5
Sarebbe molto più efficiente del metodo nella risposta sopra. Afferrare la home page di Google è molto inefficiente, soprattutto se si presenta con uno scarabocchio.
Jeshurun,

1
La risposta selezionata come corretta dovrebbe essere aggiornata con questo perché migliora la risposta. Ben fatto amico, grazie
Hugo

3
Potresti voler utilizzare g.cn/generate_204 invece di clients3.google.com/generate_204 se vuoi testare la connettività anche in Cina
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;
}

ritorna vero se Internet è effettivamente disponibile

Assicurati di avere questi due permessi

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

se http non funziona a causa della nuova sicurezza Android, ora non consentono la comunicazione in testo semplice. per ora basta passarlo.

Android: usesCleartextTraffic = "true"


Questa è la risposta migliore e più completa: è il modo più breve di fare le cose (un ping non accede all'intero sito Web), funziona indipendentemente dalla connessione che hai e funziona nel processo vinto, quindi funziona bene con le versioni Android .
MacD

cosa vuoi dire ? ecco un altro frammento che sto usando in un check del
Bilal Shahid,

ciò che intendeva dire è che questa chiamata bloccherà l'interfaccia utente e deve effettuare questa chiamata nel thread ??
Amit Hooda,

2
Questo non funziona per me ... Causato da: android.os.NetworkOnMainThreadException su android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork (StrictMode.java:1273) su java.net.InetAddress.lookupHostByName (InetAddress.java:431) alle
Maryadi Poipo,

@HyosokaPoipo non dovresti invocarlo sul thread principale. Utilizzare un thread separato o AsyncTask.
Pramesh Bajracharya,

14

Se scegli come target Lollipop o versioni successive è possibile utilizzare la nuova classe NetworkCapabilities, ovvero:

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

1
connectivityManager.getActiveNetwork();richiede API lvl23 che è Marshmallow e non Lollipop.
Saenic,

Dobbiamo anche verificare la capacità .hasCapability (NetworkCapabilities.NET_CAPABILITY_INTERNET)?
Alex

Alex capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)sembrava fare il trucco per me!
rstojano,

6

Non è necessario necessariamente stabilire una connessione HTTP completa. Potresti provare ad aprire una connessione TCP a un host noto e, se riesce, hai una connessione 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;
  }
}

Quindi controlla con:

boolean online = hostAvailable("www.google.com", 80);

la porta 80 è una porta sicura da usare?
ralphgabb,

Finché ospita un server HTTP, dovrebbe accettare una connessione TCP sulla porta 80.
Xiv

Questo dovrebbe essere usato all'interno di un AsyncTask o semplicemente chiamato nel metodo onCreate di MainActivity per esempio?
AlexioVay

@Vay tutto ciò che è relativo alla rete non dovrebbe essere eseguito sul thread principale / ui. Quindi sì, questo dovrebbe essere usato all'interno di unAsyncTask
winklerrr l'

6

Sulla base delle risposte accettate, ho creato questa classe con un ascoltatore in modo da poterlo utilizzare nel thread principale:

Primo : la classe InterntCheck che controlla la connessione Internet in background, quindi chiama un metodo listener con il risultato.

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

}

Secondo : creare un'istanza della classe nel thread principale e attendere la risposta (se hai lavorato con Firebase API per Android prima che questo ti sia familiare!).

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

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

Ora all'interno del metodo onComplete otterrai se il dispositivo è connesso a Internet o meno.


3

prova questo

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

dovrai aggiungere le seguenti autorizzazioni al tuo file manifest:

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

Quindi chiama così:

if((new ConnectionDetector(MyService.this)).isConnectingToInternet()){
    Log.d("internet status","Internet Access");
}else{
    Log.d("internet status","no Internet Access");
}


questo gay usa try catch quindi l'errore non viene mostrato per favore prima aggiungi il permesso di internet poi prova questo. funziona benissimo
Attaullah,

Lascia che ti dica come ho chiamato questo metodo nella mia attività?
Milan Gajera,

Ti ho provato a postare e ho ricevuto un errore di cui stavo scrivendo un errore nel mio blog
Milan Gajera


1

Puoi farlo usando il ConnectivityManager API per Android. Ti consente di verificare se sei connesso a Internet e il tipo di connessione Internet a cui sei connesso. Fondamentalmente, misurato o non misurato.

Per verificare la connessione a Internet.

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

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


Come si controlla se i dati mobili sono esauriti? Ciò restituisce true anche se i dati mobili sono connessi e non è presente alcun saldo di dati nell'account.
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;
}

Spero che il codice sopra ti aiuti, assicurati anche di avere il permesso di Internet nella tua app.


0

L'ultimo modo per farlo dalla documentazione è utilizzare il ConnectivityManagerper interrogare la rete attiva e determinare se ha connettività Internet.

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

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

Aggiungi queste due autorizzazioni al tuo file AndroidManifest.xml:

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

1
Non funziona :( Come dice @Buda Gavril, se sono connesso a una rete wireless che non ha accesso a Internet, questo metodo tornerà comunque vero. Test su Xiaomi 4, Android 6.0.1.
DysaniazzZ

0

Controlla il tipo di wifi in Gestione connettività:

   //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 documentazione Android descrive "TYPE_WIFI" come "Una connessione dati WIFI. I dispositivi possono supportare più di uno. "


0

Una buona soluzione per verificare se la rete attiva ha una connessione 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;
}

0

È possibile utilizzare 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

    }

Controlla questo e questo


0

Utilizzare la seguente classe , aggiornata all'ultimo livello 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;
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.