Como verificar o acesso à Internet no Android? O InetAddress nunca atinge o tempo limite


658

Eu tenho um AsyncTaskque deve verificar o acesso à rede para um nome de host. Mas o doInBackground()tempo limite nunca é excedido. Alguém tem uma pista?

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();
    }   
}

5
Para verificar se há uma conexão com a Internet, provavelmente a maneira mais confiável seria executar ping em um dos principais servidores de nomes; isso poderia ser feito, por exemplo, com if(Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8").waitFor()==0) .... Veja minha resposta para uma implementação melhor disso. Entre a resposta aceita (e muitas outras aqui), basta verificar se há uma conexão de rede , não a Internet.
Levite


4
Não use o método ping, use uma verificação HTTP. O ICMP está bloqueado em algumas redes, portanto, o ping não funcionará. Por exemplo: funciona perfeitamente no meu wifi em casa, mas não quando estou usando dados móveis na rede da Vodafone (na Hungria). Ou combine os 2 métodos como um substituto, mas tenha cuidado, porque waitFor () aguardará cerca de 20 segundos, mesmo que -w ou -W seja usado.
Tamás Bolvári


@ TamásBolvári: Melhor ainda seria enfrentá-lo na camada tcp. O que deve aproximar a velocidade de um ICMP, com a confiabilidade de uma solicitação HTTP. Eu editei a "resposta ping" em conformidade.
Levite

Respostas:


555

Conexão de rede / acesso à Internet

  • isConnectedOrConnecting()(usado na maioria das respostas) verifica qualquer conexão de rede
  • Para saber se alguma dessas redes tem acesso à Internet, use um dos seguintes

A) Faça ping em um 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;
}

+ poderia rodar na thread principal

- não funciona em alguns dispositivos antigos (Galays S3, etc.), bloqueia um pouco se não houver internet disponível.

B) Conecte-se a um soquete na Internet (avançado)

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

+muito rápido (de qualquer maneira), funciona em todos os dispositivos, muito confiável

- não pode ser executado no thread da interface do usuário

Isso funciona de maneira muito confiável em todos os dispositivos e é muito rápido. Ele precisa ser executado em uma tarefa separada (por exemplo, ScheduledExecutorServiceou AsyncTask).

Possíveis perguntas

  • É realmente rápido o suficiente?

    Sim, muito rápido ;-)

  • Não existe uma maneira confiável de verificar a Internet, além de testar algo na Internet?

    Não tanto quanto eu sei, mas me avise, e editarei minha resposta.

  • E se o DNS estiver inoperante?

    O DNS do Google (por exemplo 8.8.8.8) é o maior DNS público do mundo. A partir de 2013, atendia 130 bilhões de solicitações por dia. Digamos que seu aplicativo provavelmente não seria o assunto do dia.

  • Quais permissões são necessárias?

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

    Apenas acesso à Internet - surpresa ^^ (Como você já pensou, como alguns dos métodos sugeridos aqui podem até ter uma cola remota sobre o acesso à Internet, sem essa permissão?)

 

Extra: AsyncTaskExemplo de um tiro

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: RxJava/RxAndroidExemplo de um tiro (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 */}

22
Esta é uma grande paz de código! Achei muito útil em dispositivos que usam cartões pré-pagos! Quando ficam sem dinheiro, têm acesso à internet disponível, mas não há internet. Portanto, apenas verificar a conectividade não funcionaria. OBRIGADO!
Blejzer

10
Tenha em mente que esta abordagem é um bloqueio para que você não deve executá-lo no therad UI
Sergii

36
@ Levit Essa deve ser a resposta aceita. A resposta acima apenas verifica Rede n NÃO CONEXÃO À INTERNET . E sim, isso é muito rápido. Obrigado. Daí voto positivo.
precisa

9
Esta solução não está funcionando para todos os dispositivos. Alguns dispositivos estão sempre retornando 2 como @Salmaan afirmou. Os dispositivos que testei tinham conexão à Internet e o alvo de ping é o servidor DNS do Google - que está respondendo às solicitações de ping. Eu acho que alguns fornecedores não estão permitindo solicitações de ping. Por exemplo, testei com um tablet Samsung 10.1 (4.3) e a solução não está funcionando. Quando executo o comando ping através do utilitário de linha de comando, recebo um erro de permissão. O comando também não está funcionando em emuladores. Tenha cuidado ao usar esta solução.
Eren Yilmaz

9
Essa abordagem não funciona em todos os telefones. Ele falha, por exemplo, no Samsung Galaxy S3. Veja aqui: Por que o ping funciona em alguns dispositivos e não em outros?
Adil Hussain 24/15

1032

Se o dispositivo estiver no modo avião (ou presumivelmente em outras situações em que não há rede disponível), cm.getActiveNetworkInfo()estará null, então você precisará adicionar uma nullverificação.

Modificado ( solução de Eddie ) abaixo:

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

Adicione também a seguinte permissão ao AndroidManifest.xml:

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

Um outro pequeno ponto, se você precisar absolutamente de uma conexão de rede no momento especificado, talvez seja melhor usá-lo netInfo.isConnected()do que netInfo.isConnectedOrConnecting. Acho que isso depende do caso de uso individual.


109
você ainda deve e precisa verificar as exceções de tempo limite do http, pois pode haver situações em que uma rede está conectada, mas não há conexão real com a Internet, porque a única maneira de acessá-la é por meio de, por exemplo, VPN - desta forma, instância, conexão WI-FI, mas nenhum tráfego de Internet real. Outra situação é um servidor pendente. Esses são dois problemas que corri recentemente e o gerenciador de conexões não ajudará por lá.
meia

21
Eu concordo com a meia-noite e com o Pintu, essa resposta não deve ser a resposta aceita, não tem nada a ver com verificar se você está na internet. Por exemplo, se o telefone estiver conectado a uma rede WiFi com um portal cativo, como em um hotel, essa função retornará incorretamente verdadeira. A resposta correta é executar ping em um servidor na Internet pública.
miguel

9
quando não houver internet funcionando para o meu roteador, se eu conectar ao roteador via wifi, o código acima retornará verdadeiro. Mas, não deveria ser, certo? Você pode me ajudar
Mohan K Raj

5
Eu tive que adicionar o contexto, context.getSystemServiceou ele não funciona. Eu tenho a minha pista aqui androidhive.info/2012/07/...
Francisco Corrales Morales

1
Ótima maneira de verificar a disponibilidade da rede. Mas como verificar o acesso à Internet?
Tamás Bolvári 4/16

296

Não precisa ser complexo. A maneira mais simples e de estrutura é usar ACCESS_NETWORK_STATEpermissão e apenas criar um método conectado

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

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

Você também pode usar requestRouteToHostse tiver em mente um host e um tipo de conexão específicos (wifi / celular).

Você também precisará de:

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

no seu manifesto android.


82
é melhor fazer uma verificação nula no nível de cm.getActiveNetworkInfo (), lançando um nulo se nenhuma rede ativa estiver disponível.
Samuel

veja stackoverflow.com/a/11691676/1979773 para uma exaplanation mais profunda sobre requestRouteToHost ()
Spartako

Eu tive que adicionar o contexto, context.getSystemServiceou ele não funciona. Eu tenho a minha pista aqui androidhive.info/2012/07/...
Francisco Corrales Morales

9
Esta solução retornará true se você estiver conectado a um ponto de acesso WiFi, mesmo que esse ponto de acesso NÃO possua conectividade com a Internet.
Josh


63

Para começar getActiveNetworkInfo()a trabalhar, você precisa adicionar o seguinte ao manifesto.

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

Definitivamente, este deve estar sob a resposta correta (perda de tempo demais para descobrir o que diabos está errado).
Indrek Kõue

2
A permissão INTERNET NÃO é necessária para isso, apenas ACCESS_NETWORK_STATE. A INTERNET só é necessária se você estiver realmente fazendo conexões com locais remotos, sem consultar o estado do rádio do dispositivo.
Tom

3
Sua resposta atualmente não é realmente uma resposta, é apenas uma adição relativamente pequena a outras respostas. Se todas as outras respostas não estivessem aqui, sua resposta faria sentido? Na verdade não. Porque se que é melhor para expandir a sua resposta com código sobre como usá-lo, ou remover sua resposta e adicionar a informação em outra resposta (você não perderá nenhuma reputação)
Tim

Tenha cuidado getActiveNetworkInfo()é obsoleto em nível API 29.
Stack Overflow

46

Dê uma olhada na classe ConnectivityManager. Você pode usar essa classe para obter informações sobre as conexões ativas em um host. http://developer.android.com/reference/android/net/ConnectivityManager.html

EDIT: você pode usar

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

ou

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

e analise a enumeração Detalhada do objeto NetworkInfo retornado

EDIT EDIT: Para descobrir se você pode acessar um host, use

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

Obviamente, estou usando Context.getSystemService (Context.CONNECTIVITY_SERVICE) como um proxy para dizer

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

Não tenho certeza, mas isso parece um código para testar em que tipo de conexão de rede estou atualmente. Por exemplo, im em Wi-Fi, não há garantia de que você router wi-fi está ligado a internett ... para verificar se você realmente precisa fazer uma solicitação para um InternetServer ...
Vidar Vestnes

1
Ocorreu um erro na seção EDIT EDIT, eu deixei de fora a chamada requestRouteToHost (). Re-ler a resposta agora :)
Chinmay Kanchi

requestRouteToHost foi descontinuado.
Jahaziel 07/07

46

verifique este código ... funcionou para mim :)

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();
}

Em seguida, defino o manipulador:

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

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

        } else { // code if connected

        }   
    }
};

... e inicie o teste:

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

3
O que o Google está inoperante? Isso também requer a permissão INTERNET, que é desnecessária para a tarefa especificada. Finalmente, isso consome dados (mesmo que insignificantes). Isso apenas parece uma confusão.
Tom

28
@ Tom para ser justo, esta é provavelmente a única resposta correta. Os outros exemplos mostram apenas se uma conexão de rede está disponível e / ou se há uma conexão com essa rede, mas não responda à pergunta se essa rede também pode realmente fazer uma conexão remota (por exemplo, para um site). Então, isso responde à cartazes Q, e as outras respostas não
slinden77

2
@ dmmh Sim, infelizmente isso é verdade pelo que vi nas APIs do Android. Talvez um ping simples possa ser melhor, stackoverflow.com/questions/3905358/… . Se você estava realmente preocupado, poderia incluir uma lista de IPs para executar ping, porque, embora haja uma chance muito pequena de o Google cair, há uma chance ainda menor de que Google, Bing e Yahoo caiam no mesmo dia . Apenas meus pensamentos.
31412 Tom

10
Não faz sentido fazer essa verificação. Se você vai gastar o tempo do sistema e os recursos de rede para se conectar ao Google, poderá gastá-los se conectando ao recurso de que realmente se importa.
Benjamin

16
Na China, o Google foi bloqueado !!
Anthony #

26

Encontrado e modificado (!) Neste link :

No seu arquivo de manifesto, adicione pelo menos:

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

Você provavelmente já tem a permissão INTERNET se estiver acessando. Em seguida, uma função booleana que permite testar a conectividade é:

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

18

Eu criei esse código, é o mais simples e é apenas um booleano. perguntandoif(isOnline()){

Você obtém se há uma conexão e se pode conectar a uma página o código de status 200(conexão estável).

Certifique-se de adicionar o correto INTERNETe as ACCESS_NETWORK_STATEpermissões.

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

6
Talvez você deva substituir 200 por HttpURLConnection.HTTP_OK
Yash

5
E se o Google estiver inoperante?
Yauraw Gadav

12

Funciona para mim:

Para verificar a disponibilidade da rede:

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

Para verificar o acesso à 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;
}

Esta é uma ótima solução para verificar se um servidor está funcionando, funciona muito bem. obrigado!
Williew

1
o isOnline () não deve ser executado no thread principal, como se houvesse sinal wi-fi, mas sem internet, isso levaria muito tempo e bloqueará o thread principal.
humazed

9

Há mais de uma maneira

Primeiro, o caminho mais curto, mas ineficiente

Permissão de estado de rede necessária apenas

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

Então este método,

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

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null &&
                activeNetwork.isConnected();

        return isConnected;

    }

Como visto nas respostas, ConnectivityManageré uma solução, eu apenas o adicionei dentro de um método. Este é um método simplificado. Todo uso
ConnectivityManagerretorna true se houver acesso à rede e não à Internet, significa que se o seu WiFi estiver conectado a um roteador, mas o roteador não tiver Internet retorna true, verifica a disponibilidade da conexão

Segundo, maneira eficiente

Estado da rede e permissões da Internet necessárias

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

Então esta aula,

 public class CheckInternetAsyncTask extends AsyncTask<Void, Integer, Boolean> {

        private Context context;

        public CheckInternetAsyncTask(Context context) {
            this.context = context;
        }

        @Override
        protected Boolean doInBackground(Void... params) {

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

            assert cm != null;
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            boolean isConnected = activeNetwork != null &&
                    activeNetwork.isConnected();


            if (isConnected) {
                try {
                    HttpURLConnection urlc = (HttpURLConnection)
                            (new URL("http://clients3.google.com/generate_204")
                                    .openConnection());
                    urlc.setRequestProperty("User-Agent", "Android");
                    urlc.setRequestProperty("Connection", "close");
                    urlc.setConnectTimeout(1500);
                    urlc.connect();
                    if (urlc.getResponseCode() == 204 &&
                            urlc.getContentLength() == 0)
                        return true;

                } catch (IOException e) {
                    Log.e("TAG", "Error checking internet connection", e);
                    return false;
                }
            } else {
                Log.d("TAG", "No network available!");
                return false;
            }


            return null;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            Log.d("TAG", "result" + result);

            if(result){
                // do ur code
            }

        }


    }

Ligar CheckInternetAsyncTask

new CheckInternetAsyncTask(getApplicationContext()).execute();

Algumas explicações: -

  • você tem que verificar a Internet AsyncTask, caso contrário, pode jogar android.os.NetworkOnMainThreadExceptionem alguns casos

  • ConnectivityManager usado para verificar o acesso à rede se true envia solicitação (Ping)

  • Solicitar envio para http://clients3.google.com/generate_204, Este conhecido URL é conhecido por retornar uma página vazia com um status HTTP 204, que é mais rápido e mais eficiente do que http://www.google.com, leia isto . se você tiver um site, é preferível colocá-lo no lugar do google, somente se você o usar no aplicativo

  • O intervalo pode ser alterado (20ms -> 2000ms), 1500ms é comumente usado


2
Ótima pergunta, é triste você não ter mais pontos. Essa deve ser a resposta correta.
Jhon Fredy Trujillo Ortega,

Sou novo no Android. porém, este é bem coberto resposta e receber mais atenção @ 7569106
Mazen Embaby

1
melhor e mais completa resposta, obrigado. se alguém tiver um site perceber que essa condição deve ser semelhante a esta urlc.getResponseCode () == 200 e não precisa verificar urlc.getContentLength () == 0
AREF

o segundo acidente opção get Eu não sei porque
Nafees Ahmed

congela aplicação
nafees ahmed 13/11/18

8

De tudo que vi até agora, o caminho mais curto e limpo deve ser:

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: Isso não executa ping em nenhum host, apenas verifica o status da conexão; portanto, se o seu roteador não tiver conexão com a Internet e o dispositivo estiver conectado a ele, esse método retornará verdadeiro, embora você não tenha Internet.
Para um teste real, eu recomendaria a execução de uma solicitação HttpHead (por exemplo, www.google.com) e verificaria o status, se o seu 200 OK estiver tudo bem e o seu dispositivo tiver uma conexão com a Internet.


Eu queria colocar esse método em uma classe global, para usar essa versão para poder passar o Contexto da Atividade da qual estava chamando. Obrigado!
ryang

8

Aqui está o método que eu uso:

public boolean isNetworkAvailable(final Context context) {
    return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo() != null;
}

Melhor ainda, verifique se está "conectado":

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

Aqui está como usar o método:

if (isNetworkAvailable(context)) {
    // code here
} else {
    // code
}

Permissão necessária:

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

https://stackoverflow.com/a/16124915/950427


7

Um caso de uso importante em dispositivos móveis para garantir a existência de uma conexão real. Esse é um problema comum quando um usuário móvel entra em uma rede Wi-Fi com um "Portal Cativo", no qual ele precisa entrar. Eu uso essa função de bloqueio em segundo plano para garantir a existência de uma conexão.

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

3
+1 para realmente verificar a conectividade de ponta a ponta. Para a situação do "Portal Cativo", no entanto, descobri que muitos passarão no teste acima, mesmo que você não tenha feito login - você obtém a página de login e uma resposta de 200, independentemente do URL que você solicitar. Por isso, tento acessar uma página em meu próprio domínio que sei que não existe e garantir que recebo um 404. Como alternativa, você pode acessar uma página existente conhecida, obter 200 e verificar o conteúdo que é retornado para garantir que é o que você espera.
GreyBeardedGeek

6

Você pode percorrer todas as conexões de rede e verificar se há pelo menos uma conexão disponível:

public boolean isConnected() {
    boolean connected = false;

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

    if (cm != null) {
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();

        for (NetworkInfo ni : netInfo) {
            if ((ni.getTypeName().equalsIgnoreCase("WIFI")
                    || ni.getTypeName().equalsIgnoreCase("MOBILE"))
                    && ni.isConnected() && ni.isAvailable()) {
                connected = true;
            }

        }
    }

    return connected;
}

6

Para mim, não era uma boa prática verificar o estado da conexão na classe Activity, porque

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

deve ser chamado lá, ou você precisa enviar a instância de Activity (contexto) para a classe do manipulador de conexões para verificar o estado da conexão lá. Quando não há conexão disponível (wifi, rede), pego a exceção UnknownHostException :

JSONObject jObj = null;
Boolean responded = false;
HttpGet requestForTest = new HttpGet("http://myserver.com");
try {
    new DefaultHttpClient().execute(requestForTest);
    responded = true;
} catch (UnknownHostException e) {
    jObj = new JSONObject();
    try {
        jObj.put("answer_code", 1);
        jObj.put("answer_text", "No available connection");
    } catch (Exception e1) {}
    return jObj;
} catch (IOException e) {
    e.printStackTrace();
}

Dessa forma, eu posso lidar com esse caso junto com os outros casos da mesma classe (meu servidor sempre responde com uma string json)


6

Isso funciona para mim. Experimente.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    try {
        URL url = new URL("http://stackoverflow.com/posts/11642475/edit" );
        //URL url = new URL("http://www.nofoundwebsite.com/" );
        executeReq(url);
        Toast.makeText(getApplicationContext(), "Webpage is available!", Toast.LENGTH_SHORT).show();
    }
    catch(Exception e) {
        Toast.makeText(getApplicationContext(), "oops! webpage is not available!", Toast.LENGTH_SHORT).show();
    }
}

private void executeReq(URL urlObject) throws IOException
{
    HttpURLConnection conn = null;
    conn = (HttpURLConnection) urlObject.openConnection();
    conn.setReadTimeout(30000);//milliseconds
    conn.setConnectTimeout(3500);//milliseconds
    conn.setRequestMethod("GET");
    conn.setDoInput(true);

    // Start connect
    conn.connect();
    InputStream response =conn.getInputStream();
    Log.d("Response:", response.toString());
}}

Esta resposta não pode funcionar agora, já que não podemos acessar a rede no thread principal agora.
正宗白布鞋

1
Quero dizer, a partir do nível 11 da API, isso não funciona. Razão: developer.android.com/reference/android/os/… . Se funcionar para você, significa que você está executando esse código no dispositivo Android antigo. (antes de GB).
正宗白布鞋

Política StrictMode.ThreadPolicy = new StrictMode.ThreadPolicy.Builder () .permitAll (). Build (); StrictMode.setThreadPolicy (policy); adicionar essas duas linhas de dois seu programa para evitar rede principal exceção fio
selva_pollachi

Ok, não devo dizer que isso não pode funcionar, devo dizer que pode funcionar (pela versão antiga de destino ou pela configuração do Strictmode), mas é desencorajado. Isso pode causar ANR facilmente. (Com uma configuração de tempo limite tão alto em httpurlconnection) #
18713

ya .. você está certo .. apenas eu coloquei isso porque este também é um dos caminhos.
selva_pollachi

6

Este método oferece a opção de um método realmente rápido (para feedback em tempo real) ou um método mais lento (para verificações pontuais que exigem confiabilidade)

public boolean isNetworkAvailable(bool SlowButMoreReliable) {
    bool Result = false; 
    try {
        if(SlowButMoreReliable){
            ConnectivityManager MyConnectivityManager = null;
            MyConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo MyNetworkInfo = null;
            MyNetworkInfo = MyConnectivityManager.getActiveNetworkInfo();

            Result = MyNetworkInfo != null && MyNetworkInfo.isConnected();

        } else
        {
            Runtime runtime = Runtime.getRuntime();
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");

            int i = ipProcess.waitFor();

            Result = i== 0;

        }

    } catch(Exception ex)
    {
        //Common.Exception(ex); //This method is one you should have that displays exceptions in your log
    }
    return Result;
}

5

Estou usando esse código em vez do InetAddress:

    try {

        URL url = new URL("http://"+params[0]);

        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
        urlc.setRequestProperty("User-Agent", "Android Application:"+Z.APP_VERSION);
        urlc.setRequestProperty("Connection", "close");
        urlc.setConnectTimeout(1000 * 30); // mTimeout is in seconds
        urlc.connect();
        if (urlc.getResponseCode() == 200) {
            Main.Log("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();
    }

Seria ótimo se você tivesse esclarecido se a IOException não significa conexão com a Internet e quão confiável ela pode ser.
Milad.Nozari

5

Não é complexo verificar o status de conectividade da rede / internet Android. A DetectConnectionclasse abaixo ajudará você a verificar este status:

import android.content.Context;
import android.net.ConnectivityManager;

public class DetectConnection {
    public static boolean checkInternetConnection(Context context) {
        ConnectivityManager con_manager = (ConnectivityManager) context
                                .getSystemService(Context.CONNECTIVITY_SERVICE);

        if (con_manager.getActiveNetworkInfo() != null
            && con_manager.getActiveNetworkInfo().isAvailable()
            && con_manager.getActiveNetworkInfo().isConnected()) {
                return true;
        } else {
            return false;
        }
    }
}

Para obter mais detalhes, visite Como verificar o status da conectividade com a rede / Internet Android


5

Melhor abordagem:

public static boolean isOnline() {
    try {
    InetAddress.getByName("google.com").isReachable(3);

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

1
Eu gosto dessa abordagem, mas tenho que apontar algumas coisas. isReachable () retorna um booleano; portanto, em vez de retornar true na seção try, você pode fazê-lo como booleano conectado = InetAddress.getByName ("google.com"). isReachable (3); depois retorne conectado. Além disso, isReacheable lança as exceções IOException e IllegalArgumentException, portanto, será uma boa idéia substituir o UnknownHostException por IllegalArgumentException e incluir uma terceira captura: catch (Exceção E).
Yash

2
Porém, isReachable usa ICMP, que pode exigir privilégios de root, e usa a porta 7, que geralmente não possui serviços em execução nos sistemas mais recentes. Portanto, a melhor maneira de verificar a rota para um serviço online é pelo TCP regular; daí um voto negativo.
Yash

5

A seguir está o código da minha Utilsclasse:

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

5
public class Network {

Context context;

public Network(Context context){
    this.context = context;
}

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

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

}

Como todos os outros que não leram o problema, isso não resolve o problema, pois não verifica realmente a conexão com a Internet. Uma conexão com um ponto de acesso Wi-Fi local retornará verdadeiro, mesmo que o ponto de acesso não permita que você acesse a Internet.
Pedro Pombeiro

5

Você pode usar esse método para detectar a disponibilidade da rede.

public static boolean isDeviceOnline(Context context) {
        boolean isConnectionAvail = false;
        try {
            ConnectivityManager cm = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            return netInfo.isConnected();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isConnectionAvail;
    }

5

Apliquei a solução fornecida pelo @Levit e criei a função que não chamará a Solicitação Http extra.

Resolverá o erro Unable to Resolve Host

public static boolean isInternetAvailable(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork == null) return false;

    switch (activeNetwork.getType()) {
        case ConnectivityManager.TYPE_WIFI:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        case ConnectivityManager.TYPE_MOBILE:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        default:
            return false;
    }
    return false;
}

private static boolean isInternet() {

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

    return false;
}

Agora chame assim,

if (!isInternetAvailable(getActivity())) {
     //Show message
} else {
     //Perfoem the api request
}

4

1
Mas o método descrito lá realmente não verifica a conexão com a Internet, apenas verifica se uma conexão foi estabelecida (se tem acesso à Internet ou não). O título desse documento oficial é realmente enganador.
Tiago

2
Dar uma resposta para a pergunta é melhor do que apenas postar um link para informações. E se o link ficar morto? Não teremos resposta.
Jose Llausas 21/09/2015

4

Eu passei por todas as respostas e venho com a minha própria resposta, que primeiro verifica se a Internet está disponível e se a Internet está disponível e depois verifica se está ativa ou não.

Incluí todos os métodos e classes necessários para verificar a conexão ativa com a Internet.

NetworkUtils.class

public class NetworkUtils {

    public static final int STATUS_CONNECTED = 0 ;

    public static boolean isInternetAvailable(Context ctx){
        ConnectivityManager cm = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    public static int isInternetActiveWithPing() {
        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int exitValue = process.waitFor();
            return exitValue;
        } catch (Exception ex) {
            return -1;
        }
    }

    public static boolean isInternetActiveWithInetAddress() {
        try {
            InetAddress inetAddress = InetAddress.getByName("www.google.com");
            return inetAddress != null && !inetAddress.toString().equals("");
        } catch (Exception ex) {
            return false;
        }
    }

    public static void displayInternetConnectionMessage(Context ctx){
        Toast.makeText(ctx, "Check Internet Connection", Toast.LENGTH_SHORT).show();
    }
}

Você pode verificar se a Internet está ativa usando o código abaixo:

 private void checkInternetConnection() {
        if (NetworkUtils.isInternetAvailable(this)) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (NetworkUtils.isInternetActiveWithPing() == NetworkUtils.STATUS_CONNECTED) {
                        performNetworkingOperations();
                    } else {
                        if (NetworkUtils.isInternetActiveWithInetAddress()) {
                            performNetworkingOperations();
                        } else {
                            displayConnectionMessage();
                        }
                    }
                }
            }).start();

        } else {
            displayConnectionMessage();
        }
    }

    private void performNetworkingOperations() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "Internet is Available", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void displayConnectionMessage() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                NetworkUtils.displayInternetConnectionMessage(MainActivity.this);
            }
        });
    }

Melhor pacote de threading em seus NetworkUtils e, portanto, desenvolvedor "força" para não mis usar o seu método
Ewoks

Para remover uma condição extra. if ((NetworkUtils.isInternetActiveWithPing () == NetworkUtils.STATUS_CONNECTED) || NetworkUtils.isInternetActiveWithInetAddress ()) {// Faça a operação de rede} else {// Mensagem de erro}
Jawad Zeb

4

Muito importante para verificar se temos conectividade com isAvailable () e se é possível estabelecer uma conexão com isConnected ()

private static ConnectivityManager manager;

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

e você pode determinar o tipo de WiFi ativo da rede :

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

ou móvel Móvil :

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

não esqueça as permissões:

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

Bom resumo dos componentes de conectividade do dispositivo, basta envolvê-los em instruções try / catch para evitar falhas. Da mesma forma, basta fazer suas chamadas HttpURLConnection de rotina, contanto que eles estão envoltos em tratamento de erros, em breve você vai saber se você tem ou não uma conexão com a internet
rangi

4

Kotlin e corotinas

Eu coloquei a função em a ViewModel, que possui o viewModelScope. Usando um observável LiveData, informo uma atividade sobre a conexão.

ViewModel

 fun checkInternetConnection() {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val timeoutMs = 3000
                    val socket = Socket()
                    val socketAddress = InetSocketAddress("8.8.8.8", 53)

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

                    withContext(Dispatchers.Main) {
                        _connection.value = true
                    }
                }
                catch(ex: IOException) {
                    withContext(Main) {
                        _connection.value = false
                    }
                }
            }
        }
    }
 private val _connection = MutableLiveData<Boolean>()
 val connection: LiveData<Boolean> = _connection

Atividade

 private fun checkInternetConnection() {
     viewModel.connection.observe(this) { hasInternet ->
         if(!hasInternet) {
             //hasn't connection
         }
         else {
            //has connection
         }
     }
  }

3

Basta criar a seguinte classe que verifica a conexão à Internet:

public class ConnectionStatus {

    private Context _context;

    public ConnectionStatus(Context context) {
        this._context = context;
    }

    public boolean isConnectionAvailable() {
        ConnectivityManager connectivity = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null)
                for (int i = 0; i < info.length; i++)
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
        }
        return false;
    }
}

Essa classe simplesmente contém um método que retorna o valor booleano do status da conexão. Portanto, em termos simples, se o método encontrar uma conexão válida com a Internet, o valor retornado será true, caso contrário, falsese nenhuma conexão válida for encontrada.

O método a seguir em MainActivity chama o resultado do método descrito anteriormente e solicita que o usuário aja de acordo:

public void addListenerOnWifiButton() {
        Button btnWifi = (Button)findViewById(R.id.btnWifi);

        iia = new ConnectionStatus(getApplicationContext());

        isConnected = iia.isConnectionAvailable();
        if (!isConnected) {
            btnWifi.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
                    Toast.makeText(getBaseContext(), "Please connect to a hotspot",
                            Toast.LENGTH_SHORT).show();
                }
            });
        }
        else {
            btnWifi.setVisibility(4);
            warning.setText("This app may use your mobile data to update events and get their details.");
        }
    }

No código acima, se o resultado for falso, (portanto, não há conexão com a Internet, o usuário é levado ao painel wi-fi do Android, onde é solicitado a se conectar a um ponto de acesso wi-fi.


3

Atualização 29/06/2015 Se você estiver usando o Xamarin.Android e quiser verificar a conectividade, poderá usar um pacote Nuget que forneceria essa funcionalidade em várias plataformas. Bons candidatos estão aqui e aqui . [Fim da atualização]

As respostas acima são muito boas, mas estão todas em Java e quase todas verificam a conectividade. No meu caso, eu precisava ter conectividade com um tipo específico de conexão e estou desenvolvendo no Xamarin.Android. Além disso, não passo uma referência às minhas atividades Contexto na camada Hardware, uso o Contexto do Aplicativo. Então, aqui está a minha solução, caso alguém venha aqui com requisitos semelhantes. No entanto, ainda não fiz o teste completo, atualizará a resposta assim que terminar o teste

using Android.App;
using Android.Content;
using Android.Net;

namespace Leopard.Mobile.Hal.Android
{
    public class AndroidNetworkHelper
    {
        public static AndroidNetworkStatus GetWifiConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Wifi);
        }

        public static AndroidNetworkStatus GetMobileConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Mobile);
        }

        #region Implementation

        private static AndroidNetworkStatus GetConnectivityStatus(ConnectivityType connectivityType)
        {
            var connectivityManager = (ConnectivityManager)Application.Context.GetSystemService(Context.ConnectivityService);
            var wifiNetworkInfo = connectivityManager.GetNetworkInfo(connectivityType);
            var result = GetNetworkStatus(wifiNetworkInfo);
            return result;
        }

        private static AndroidNetworkStatus GetNetworkStatus(NetworkInfo wifiNetworkInfo)
        {
            var result = AndroidNetworkStatus.Unknown;
            if (wifiNetworkInfo != null)
            {
                if (wifiNetworkInfo.IsAvailable && wifiNetworkInfo.IsConnected)
                {
                    result = AndroidNetworkStatus.Connected;
                }
                else
                {
                    result = AndroidNetworkStatus.Disconnected;
                }
            }
            return result;
        } 

        #endregion
    }

    public enum AndroidNetworkStatus
    {
        Connected,
        Disconnected,
        Unknown
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.