¿Cómo comprobar el acceso a Internet en Android? InetAddress nunca caduca
Obtuve un AsyncTask
que 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();
}
}
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 null
marca.
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.
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, ScheduledExecutorService
o 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 {
}
});
AsyncTask
Extra: ejemplo de una sola vez
Precaución: Esto muestra otro ejemplo de cómo realizar la solicitud. Sin embargo, dado que AsyncTask
está 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 */ });