Question Comment vérifier l'accès à Internet sur Android? InetAddress n'expire jamais


j'ai un AsyncTask Cela est supposé vérifier l'accès réseau à un nom d'hôte. Mais le doInBackground() n'est jamais expiré. Quelqu'un a une idée?

public class HostAvailabilityTask extends AsyncTask<String, Void, Boolean> {

    private Main main;

    public HostAvailabilityTask(Main main) {
        this.main = main;
    }

    protected Boolean doInBackground(String... params) {
        Main.Log("doInBackground() isHostAvailable():"+params[0]);

        try {
            return InetAddress.getByName(params[0]).isReachable(30); 
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;       
    }

    protected void onPostExecute(Boolean... result) {
        Main.Log("onPostExecute()");

        if(result[0] == false) {
            main.setContentView(R.layout.splash);
            return;
        }

        main.continueAfterHostCheck();
    }   
}

562
2017-10-13 14:59


origine


Réponses:


Connexion réseau / accès Internet

  • isConnectedOrConnecting() (utilisé dans la plupart des réponses) vérifie réseau connexion
  • Pour savoir si l'un de ces réseaux a l'Internet accès, utilisez l'un des éléments suivants

A) Ping un serveur (facile)

// ICMP 
public boolean isOnline() {
    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    }
    catch (IOException e)          { e.printStackTrace(); }
    catch (InterruptedException e) { e.printStackTrace(); }

    return false;
}

+ pourrait tourner sur le fil principal

- ne fonctionne pas sur certains anciens appareils (Galay S3, etc.), il bloque un peu si internet n'est pas disponible.

B) Connexion à une prise sur Internet (avancé)

// TCP/HTTP/DNS (depending on the port, 53=DNS, 80=HTTP, etc.)
public boolean isOnline() {
    try {
        int timeoutMs = 1500;
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);

        sock.connect(sockaddr, timeoutMs);
        sock.close();

        return true;
    } catch (IOException e) { return false; }
}

+ très rapide (de toute façon), fonctionne sur tous les appareils, très fiable

- ne peut pas s'exécuter sur le thread d'interface utilisateur

Cela fonctionne de manière très fiable, sur tous les appareils, et est très rapide. Il doit cependant exécuter une tâche distincte (par ex. ScheduledExecutorService ou AsyncTask).

Questions possibles

  • Est-ce vraiment assez rapide?

    Oui, très vite ;-)

  • N'y a-t-il pas un moyen fiable de vérifier Internet, autre que de tester quelque chose sur Internet?

    Pas aussi loin que je sache, mais laissez-moi savoir, et je vais modifier ma réponse.

  • Que faire si le DNS est en panne?

    Google DNS (par ex. 8.8.8.8) est le plus grand DNS public du monde. En 2013, il a servi 130 milliards de demandes par jour. Disons simplement que votre application ne sera probablement pas la meilleure de la journée.

  • Quelles autorisations sont requises?

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

    Juste l'accès à Internet - surprise ^^ (Btw avez-vous déjà pensé, comment certaines des méthodes suggérées ici pourraient même avoir une colle à distance sur l'accès à Internet, sans cette permission?)

Extra: One-shot AsyncTask Exemple

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

    private Consumer mConsumer;
    public  interface Consumer { void accept(Boolean internet); }

    public  InternetCheck(Consumer consumer) { mConsumer = consumer; execute(); }

    @Override protected Boolean doInBackground(Void... voids) { try {
        Socket sock = new Socket();
        sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
        sock.close();
        return true;
    } catch (IOException e) { return false; } }

    @Override protected void onPostExecute(Boolean internet) { mConsumer.accept(internet); }
}

///////////////////////////////////////////////////////////////////////////////////
// Usage

    new InternetCheck(internet -> { /* do something with boolean response */ });

Extra: One-shot RxJava/RxAndroid Exemple (Kotlin)

fun hasInternetConnection(): Single<Boolean> {
  return Single.fromCallable {
    try {
      // Connect to Google DNS to check for connection
      val timeoutMs = 1500
      val socket = Socket()
      val socketAddress = InetSocketAddress("8.8.8.8", 53)

      socket.connect(socketAddress, timeoutMs)
      socket.close()

      true
    } catch (e: IOException) {
      false
    }
  }
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
}

///////////////////////////////////////////////////////////////////////////////////
    // Usage

    hasInternetConnection().subscribe { hasInternet -> /* do something */}

363
2017-12-05 09:20



@ Eddie. Juste une modification mineure à votre solution - si l'appareil est en mode avion (ou vraisemblablement dans d'autres situations où il n'y a pas de réseau disponible), cm.getActiveNetworkInfo() sera null, vous devez donc ajouter un null vérifier.

Solution modifiée ci-dessous:

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

Ajoutez également l'autorisation suivante à AndroidManifest.xml:

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

Un autre petit point, si vous avez absolument besoin d'une connexion réseau à un moment donné, alors il pourrait être préférable d'utiliser netInfo.isConnected() plutôt que netInfo.isConnectedOrConnecting. Je suppose que cela dépend du cas d'utilisation individuel.


998
2017-10-24 16:28



Pas besoin d'être complexe. La manière la plus simple et la plus structurée est d'utiliser ACCESS_NETWORK_STATE permission et juste faire une méthode connectée

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

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

Vous pouvez aussi utiliser requestRouteToHost si vous avez un hôte particualr et un type de connexion (wifi / mobile) à l'esprit.

Vous aurez également besoin de:

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

dans votre manifeste android.


287
2018-01-04 20:01



Obtenir getActiveNetworkInfo() Pour travailler, vous devez ajouter ce qui suit au manifeste.

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

63
2017-09-27 10:05



vérifiez ce code ... ça a marché pour moi :)

public static void isNetworkAvailable(final Handler handler, final int timeout) {
    // ask fo message '0' (not connected) or '1' (connected) on 'handler'
    // the answer must be send before before within the 'timeout' (in milliseconds)

    new Thread() {
        private boolean responded = false;   
        @Override
        public void run() { 
            // set 'responded' to TRUE if is able to connect with google mobile (responds fast) 
            new Thread() {      
                @Override
                public void run() {
                    HttpGet requestForTest = new HttpGet("http://m.google.com");
                    try {
                        new DefaultHttpClient().execute(requestForTest); // can last...
                        responded = true;
                    } 
                    catch (Exception e) {
                    }
                } 
            }.start();

            try {
                int waited = 0;
                while(!responded && (waited < timeout)) {
                    sleep(100);
                    if(!responded ) { 
                        waited += 100;
                    }
                }
            } 
            catch(InterruptedException e) {} // do nothing 
            finally { 
                if (!responded) { handler.sendEmptyMessage(0); } 
                else { handler.sendEmptyMessage(1); }
            }
        }
    }.start();
}

Ensuite, je définis le gestionnaire:

Handler h = new Handler() {
    @Override
    public void handleMessage(Message msg) {

        if (msg.what != 1) { // code if not connected

        } else { // code if connected

        }   
    }
};

... et lancez le test:

isNetworkAvailable(h,2000); // get the answser within 2000 ms

47
2018-04-27 11:41



Jetez un oeil à la classe ConnectivityManager. Vous pouvez utiliser cette classe pour obtenir des informations sur les connexions actives sur un hôte. http://developer.android.com/reference/android/net/ConnectivityManager.html

EDIT: Vous pouvez utiliser

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE) 

ou

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_WIFI) 

et analyser l'énumération DetailedState de l'objet NetworkInfo renvoyé

EDIT EDIT: Pour savoir si vous pouvez accéder à un hôte, vous pouvez utiliser

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .requestRouteToHost(TYPE_WIFI, int hostAddress)

Évidemment, j'utilise Context.getSystemService (Context.CONNECTIVITY_SERVICE) comme proxy pour dire

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

44
2017-10-13 15:38



Trouvé à et modifié (!) À partir de ce lien :

Ajoutez dans votre fichier manifeste au moins:

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

Vous avez probablement déjà l'autorisation INTERNET si vous y accédez. Alors une fonction booléenne qui permet de tester la connectivité est:

private boolean checkInternetConnection() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    // test for connection
    if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected()) {
        return true;
    } else {
        Log.v(TAG, "Internet Connection Not Present");
        return false;
    }
}

25
2018-01-11 10:29



J'ai fait ce code, c'est le plus simple et c'est juste un booléen. en demandant if(isOnline()){

Vous obtenez s'il y a une connexion et si elle peut se connecter à une page le code d'état 200 (connexion stable).

Assurez-vous d'ajouter le bon INTERNET et ACCESS_NETWORK_STATE autorisations

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(3000);
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return new Boolean(true);
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return false;
}

15
2017-07-19 13:27



Cela fonctionne pour moi:

Pour vérifier la disponibilité du réseau:

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

Pour vérifier l'accès à Internet:

public Boolean isOnline() {
    try {
        Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
        int returnVal = p1.waitFor();
        boolean reachable = (returnVal==0);
        return reachable;
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

11
2018-03-07 16:57



De tout ce que j'ai vu jusqu'ici le plus court et le plus propre devrait être:

public final static boolean isConnected( Context context )
{   
   final ConnectivityManager connectivityManager = 
         (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );  
   final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();    
   return networkInfo != null && networkInfo.isConnected();
}

PS: Cela ne fait pas de ping sur un hôte, il vérifie simplement le statut de connexion, donc si votre routeur n'a pas de connexion internet et que votre périphérique est connecté, cette méthode retournera vrai Même si vous n'avez pas internet.
Pour un test réel, je recommande d'exécuter une requête HttpHead (par exemple sur www.google.com) et vérifier le statut, si son 200 OK tout va bien et votre appareil dispose d'une connexion Internet.


8
2017-09-19 08:10



Un cas d'utilisation important sur les appareils mobiles pour assurer une connexion réelle existe. C'est un problème courant lorsqu'un utilisateur mobile entre dans un réseau Wifi avec un "portail captif", dans lequel il doit se connecter. J'utilise cette fonction de blocage en arrière-plan pour m'assurer qu'une connexion existe.

/*
 * Not Thread safe. Blocking thread. Returns true if it
 * can connect to URL, false and exception is logged.
 */
public boolean checkConnectionHttps(String url){
    boolean responded = false;
    HttpGet requestTest = new HttpGet(url);
    HttpParams params = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(params, 3000);
    HttpConnectionParams.setSoTimeout(params, 5000);
    DefaultHttpClient client = new DefaultHttpClient(params);
    try {
        client.execute(requestTest);
        responded = true;
    } catch (ClientProtocolException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
    } catch (IOException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
        e.printStackTrace();
    }
    return responded;
}

7
2018-06-13 16:36