Connessione di rete / accesso a Internet
isConnectedOrConnecting()
(utilizzato nella maggior parte delle risposte) verifica l'eventuale connessione di rete
- Per sapere se una di queste reti ha accesso a Internet , utilizzare una delle seguenti opzioni
A) Ping a Server (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;
}
+
potrebbe essere eseguito sul thread principale
-
non funziona su alcuni vecchi dispositivi (Galays S3, ecc.), si blocca per un po 'se non è disponibile internet.
B) Connessione a una presa su Internet (avanzata)
// 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; }
}
+
molto veloce (in entrambi i casi), funziona su tutti i dispositivi, molto affidabile
-
non può essere eseguito sul thread dell'interfaccia utente
Funziona in modo molto affidabile, su ogni dispositivo ed è molto veloce. Deve tuttavia essere eseguito in un'attività separata (ad es. ScheduledExecutorService
O AsyncTask
).
Possibili domande
È davvero abbastanza veloce?
Sì, molto velocemente ;-)
Non esiste un modo affidabile per controllare Internet, oltre a provare qualcosa su Internet?
Non per quanto ne so, ma fammi sapere, e modificherò la mia risposta.
Cosa succede se il DNS è inattivo?
Google DNS (ad es. 8.8.8.8
) È il più grande DNS pubblico al mondo. A partire dal 2013 ha servito 130 miliardi di richieste al giorno. Diciamo solo che la tua app probabilmente non sarebbe il discorso del giorno.
Quali autorizzazioni sono necessarie?
<uses-permission android:name="android.permission.INTERNET" />
Solo accesso a Internet - sorpresa ^^ (A proposito, hai mai pensato, come alcuni dei metodi suggeriti qui potrebbero anche avere una colla remota sull'accesso a Internet, senza questa autorizzazione?)
Extra: One-shot AsyncTask
Esempio
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: esempio One-shot 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 */}
if(Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8").waitFor()==0) ...
. Vedi la mia risposta per una migliore implementazione di questo. Tra la risposta accettata (e molti altri qui) basta cercare una connessione di rete , non Internet.