Como verificar se a conexão com a internet está presente em java?

Como você verifica se você pode se conectar à internet via java? Um caminho seria:

final URL url = new URL("http://www.google.com"); final URLConnection conn = url.openConnection(); ... if we got here, we should have net ... 

Mas há algo mais apropriado para executar essa tarefa, especialmente se você precisar fazer verificações consecutivas com muita freqüência e uma perda de conexão com a Internet é altamente provável?

Você deve se conectar ao local que sua aplicação real precisa. Caso contrário, você está testando se tem uma conexão com algum lugar irrelevante (o Google, neste caso).

Em particular, se você estiver tentando falar com um serviço da Web, e se estiver no controle do serviço da Web, seria uma boa ideia ter um método da Web “obter o status” barato. Dessa forma, você tem uma ideia muito melhor de saber se sua chamada “real” provavelmente funcionará.

Em outros casos, apenas abrir uma conexão com uma porta que deveria estar aberta pode ser suficiente – ou enviar um ping. InetAddress.isReachable pode muito bem ser uma API apropriada para suas necessidades aqui.

O código que você basicamente forneceu, além de uma chamada para connect deve ser suficiente. Então, sim, pode ser que apenas o Google não esteja disponível, mas algum outro site que você precisa contatar está ligado, mas qual é a probabilidade disso? Além disso, esse código só deve ser executado quando você realmente não acessa seu recurso externo (em um bloco catch para tentar descobrir qual foi a causa da falha), então eu diria que se seu recurso externo de interesse e o Google forem Não há chances disponíveis de você ter um problema de conectividade de rede.

 private static boolean netIsAvailable() { try { final URL url = new URL("http://www.google.com"); final URLConnection conn = url.openConnection(); conn.connect(); conn.getInputStream().close(); return true; } catch (MalformedURLException e) { throw new RuntimeException(e); } catch (IOException e) { return false; } } 

As pessoas sugeriram usar INetAddress.isReachable. O problema é que alguns sites configuram seus firewalls para bloquear mensagens Ping ICMP. Portanto, um “ping” pode falhar mesmo que o serviço da Web esteja acessível.

E, claro, o inverso também é verdade. Um host pode responder a um ping mesmo que o servidor da web esteja inativo.

E, é claro, uma máquina pode não conseguir se conectar diretamente a determinados (ou todos) servidores da web devido a restrições de firewall locais.

O problema fundamental é que “pode ​​se conectar à internet” é uma questão mal definida, e esse tipo de coisa é difícil de testar sem:

  1. informações sobre a máquina do usuário e ambiente de rede “local”, e
  2. informações sobre o que o aplicativo precisa acessar.

Então, geralmente, a solução mais simples é que um aplicativo tente acessar o que ele precisa acessar e recorra à inteligência humana para fazer o diagnóstico.

Se você estiver no java 6, pode usar NetworkInterface para verificar as interfaces de rede disponíveis. Ou seja, algo assim:

 Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface interf = interfaces.nextElement(); if (interf.isUp() && !interf.isLoopback()) return true; } 

Ainda não tentei isso.

Este código:

 "127.0.0.1".equals(InetAddress.getLocalHost().getHostAddress().toString()); 

Retorna – para mim – true se estiver off-line e false , caso contrário. (bem, não sei se isso é verdade para todos os computadores).

Isso funciona muito mais rápido que as outras abordagens, aqui em cima.


EDIT: eu encontrei este trabalho apenas, se o “flip switch” (em um laptop), ou alguma outra opção definida pelo sistema, para a conexão com a internet, está desligado. Ou seja, o próprio sistema sabe não procurar por nenhum endereço IP.

Esse código deve fazer o trabalho de forma confiável.

Observe que ao usar a instrução try-with-resources , não precisamos fechar os resources.

 import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; public class InternetAvailabilityChecker { public static boolean isInternetAvailable() throws IOException { return isHostAvailable("google.com") || isHostAvailable("amazon.com") || isHostAvailable("facebook.com")|| isHostAvailable("apple.com"); } 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; } } } 

Eu costumo dividi-lo em três etapas.

  1. Primeiro vejo se consigo resolver o nome de domínio para um endereço IP.
  2. Eu então tento conectar via TCP (porta 80 e / ou 443) e fechar graciosamente.
  3. Por fim, vou emitir uma solicitação HTTP e verificar uma resposta de 200 de volta.

Se falhar a qualquer momento, forneço a mensagem de erro apropriada ao usuário.

 URL url=new URL("http://[any domain]"); URLConnection con=url.openConnection(); /*now errors WILL arise here, i hav tried myself and it always shows "connected" so we'll open an InputStream on the connection, this way we know for sure that we're connected to d internet */ /* Get input stream */ con.getInputStream(); 

Coloque as declarações acima em try catch blocks e se uma exceção for travada significa que não há conexão com a Internet estabelecida. 🙂

O código usando NetworkInterface para aguardar a rede funcionou para mim até eu mudar de endereço de rede fixa para DHCP. Um pequeno aprimoramento faz com que ele funcione também com o DHCP:

 Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface interf = interfaces.nextElement(); if (interf.isUp() && !interf.isLoopback()) { List adrs = interf.getInterfaceAddresses(); for (Iterator iter = adrs.iterator(); iter.hasNext();) { InterfaceAddress adr = iter.next(); InetAddress inadr = adr.getAddress(); if (inadr instanceof Inet4Address) return true; } } } 

Isso funciona para o Java 7 no openSuse 13.1 para rede IPv4. O problema com o código original é que, embora a interface esteja ativa após a retomada da suspensão, um endereço de rede IPv4 ainda não foi atribuído. Depois de aguardar essa atribuição, o programa pode se conectar aos servidores. Mas não tenho ideia do que fazer no caso do IPv6.

InetAddress.isReachable algum dia retornará false se existir conexão com a Internet.

Um método alternativo para verificar a disponibilidade da Internet em java é: Essa function faz um ping real do ICMP ECHO .

 public static boolean isReachableByPing(String host) { try{ String cmd = ""; if(System.getProperty("os.name").startsWith("Windows")) { // For Windows cmd = "ping -n 1 " + host; } else { // For Linux and OSX cmd = "ping -c 1 " + host; } Process myProcess = Runtime.getRuntime().exec(cmd); myProcess.waitFor(); if(myProcess.exitValue() == 0) { return true; } else { return false; } } catch( Exception e ) { e.printStackTrace(); return false; } } 

1) Descubra onde seu aplicativo precisa se conectar.

2) Configure um processo de trabalho para verificar InetAddress.isReachable para monitorar a conexão com esse endereço.

Este código está contido em uma class de teste jUnit que eu uso para testar se uma conexão está disponível. Eu sempre recebo uma conexão, mas se você verificar o tamanho do conteúdo, ele deve ser -1 se não for conhecido:

  try { URL url = new URL("http://www.google.com"); URLConnection connection = url.openConnection(); if(connection.getContentLength() == -1){ fail("Failed to verify connection"); } } catch (IOException e) { fail("Failed to open a connection"); e.printStackTrace(); } 
 public boolean checkInternetConnection() { boolean status = false; Socket sock = new Socket(); InetSocketAddress address = new InetSocketAddress("www.google.com", 80); try { sock.connect(address, 3000); if(sock.isConnected()) status = true; } catch(Exception e) { status = false; } finally { try { sock.close(); } catch(Exception e){} } return status; } 

Há também uma opção --offline que talvez resulte no comportamento desejado.

 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView mtv=findViewById(R.id.textv); ConnectivityManager connectivityManager= (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if(((Network)connectivityManager.getActiveNetwork())!=null) mtv.setText("true"); else mtv.setText("fasle"); } } }