¿Cómo comprobar el acceso a Internet en Android? InetAddress nunca caduca

Resuelto Vidar Vestnes asked hace 54 años • 64 respuestas

Obtuve un AsyncTaskque se supone debe verificar el acceso de red a un nombre de host. Pero doInBackground()nunca se agota el tiempo. ¿Alguien tiene una idea?

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();
    }   
}
Vidar Vestnes avatar Jan 01 '70 08:01 Vidar Vestnes
Aceptado

Si el dispositivo está en modo avión (o presumiblemente en otras situaciones donde no hay una red disponible), cm.getActiveNetworkInfo()será null, por lo que deberás agregar una nullmarca.

Modificado ( solución de Eddie ) a continuación:

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

Agregue también el siguiente permiso a AndroidManifest.xml:

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

Otro pequeño punto: si es absolutamente necesario una conexión de red en un momento dado, entonces podría ser mejor usarla netInfo.isConnected()en lugar de netInfo.isConnectedOrConnecting. Sin embargo, supongo que esto depende del caso de uso individual.

gar avatar Oct 24 '2010 16:10 gar

Conexión de red / acceso a Internet

  • isConnectedOrConnecting()(utilizado en la mayoría de las respuestas) comprueba si hay alguna conexión de red
  • Para saber si alguna de esas redes tiene acceso a Internet , utilice una de las siguientes

A) Hacer ping a un servidor (fácil)

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

+podría ejecutarse en el hilo principal

-no funciona en algunos dispositivos antiguos (Galays S3, etc.), se bloquea por un tiempo si no hay Internet disponible.

B) Conectarse a un enchufe en Internet (avanzado)

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

+muy rápido (de cualquier manera), funciona en todos los dispositivos, muy confiable

-no se puede ejecutar en el hilo de la interfaz de usuario

Esto funciona de manera muy confiable en todos los dispositivos y es muy rápido. Sin embargo, debe ejecutarse en una tarea separada (por ejemplo, ScheduledExecutorServiceo AsyncTask).

Posibles preguntas

  • ¿Es realmente lo suficientemente rápido?

    Sí, muy rápido ;-)

  • ¿No existe una forma confiable de consultar Internet, aparte de probar algo en Internet?

    No que yo sepa, pero házmelo saber y editaré mi respuesta.

  • ¿Qué pasa si el DNS no funciona?

    El DNS de Google (p. ej. 8.8.8.8) es el DNS público más grande del mundo. En 2018, manejaba más de un billón de consultas al día [ 1 ]. Digamos que su aplicación probablemente no sería la comidilla del día.

  • ¿Qué permisos se requieren?

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

    Solo acceso a Internet: sorpresa ^^ (Por cierto, ¿alguna vez has pensado en cómo algunos de los métodos sugeridos aquí podrían incluso tener un vínculo remoto con el acceso a Internet, sin este permiso?)

 

Extra: ejemplo de una sola vez RxJava/RxAndroid(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 */}

Extra: ejemplo de una sola vez RxJava/RxAndroid(Java)

public static Single<Boolean> hasInternetConnection() {
    return Single.fromCallable(() -> {
        try {
            // Connect to Google DNS to check for connection
            int timeoutMs = 1500;
            Socket socket = new Socket();
            InetSocketAddress socketAddress = new InetSocketAddress("8.8.8.8", 53);

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

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

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

    hasInternetConnection().subscribe((hasInternet) -> {
        if(hasInternet) {

        }else {

        }
    });

AsyncTaskExtra: ejemplo de una sola vez

Precaución: Esto muestra otro ejemplo de cómo realizar la solicitud. Sin embargo, dado que AsyncTaskestá en desuso, debe ser reemplazado por la programación de subprocesos de su aplicación, Kotlin Coroutines, Rx, ...

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 */ });
Levite avatar Dec 05 '2014 09:12 Levite