Как проверить доступ в интернет на Android? InetAddress никогда не истекает


658

Я получил, AsyncTaskчто должен проверить доступ к сети по имени хоста. Но время doInBackground()никогда не истекает. У кого-нибудь есть подсказка?

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
Чтобы проверить подключение к Интернету, вероятно, наиболее надежным способом будет пинговать один из основных серверов имен, это можно сделать, например, с помощью if(Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8").waitFor()==0) .... Смотрите мой ответ для более хорошей реализации этого. Кстати, принятый ответ (и многие другие здесь) просто проверьте подключение к сети , а не к Интернету.
Левит


4
Не используйте метод ping, вместо этого используйте проверку HTTP. ICMP заблокирован в некоторых сетях, поэтому ping не будет работать. Например: он отлично работает на моем домашнем Wi-Fi, но не работает, когда я использую мобильные данные в сети Vodafone (в Венгрии). Или объедините 2 метода как запасной вариант, но будьте осторожны, так как waitFor () будет ждать около 20 секунд, даже если используется -w или -W.
Тамас Болвари

Проверьте это: stackoverflow.com/a/39766506/3806413
0xAliHn

@ TamásBolvári: Еще лучше было бы заняться этим на уровне TCP. Что должно приблизить вас к скорости ICMP с надежностью HTTP-запроса. Я отредактировал «ответ пинга» соответственно.
Левит

Ответы:


556

Сетевое подключение / доступ в интернет

  • isConnectedOrConnecting()(используется в большинстве ответов) проверяет любое сетевое соединение
  • Чтобы узнать, есть ли у какой-либо из этих сетей доступ в Интернет, воспользуйтесь одним из следующих

A) Пинг сервера (легко)

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

+ может работать в главном потоке

- не работает на некоторых старых устройствах (Galays S3 и т. д.), он блокируется некоторое время, если интернет недоступен.

Б) Подключение к сокету в интернете (дополнительно)

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

+очень быстрый (в любом случае), работает на всех устройствах, очень надежный

- не может работать в потоке пользовательского интерфейса

Это работает очень надежно на каждом устройстве и очень быстро. Он должен выполняться в отдельной задаче (например, ScheduledExecutorServiceили AsyncTask).

Возможные вопросы

  • Это действительно достаточно быстро?

    Да, очень быстро ;-)

  • Нет ли надежного способа проверить интернет, кроме тестирования чего-либо в интернете?

    Не настолько, насколько я знаю, но дайте мне знать, и я отредактирую свой ответ.

  • Что делать, если DNS не работает?

    Google DNS (например 8.8.8.8) является крупнейшим общедоступным DNS в мире. По состоянию на 2013 год он обслуживал 130 миллиардов запросов в день. Скажем так, ваше приложение, вероятно, не будет темой дня.

  • Какие разрешения требуются?

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

    Просто доступ в интернет - сюрприз ^^ (Кстати, вы когда-нибудь задумывались над тем, как некоторые из предложенных здесь способов могли бы иметь хоть какой-то удаленный признак доступа в интернет без этого разрешения?)

 

Дополнительно: AsyncTaskпример с одним выстрелом

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

Дополнительно: RxJava/RxAndroidПример с одним выстрелом (Котлин)

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
Это большой мир кода! Я нашел это очень полезным на устройствах, которые используют карты предоплаты! Когда у них заканчиваются деньги, у них есть доступ в интернет, но нет интернета. Так что просто проверка подключения не подойдет. БЛАГОДАРЮ ВАС!
Блейзер

10
Имейте в виду, что этот подход является блокирующим, поэтому вы не должны выполнять его в пользовательском интерфейсе Therad
Сергей

36
@Levit Это должен быть принятый ответ. Выше ответ просто проверяет Сеть НЕ ПОДКЛЮЧЕНИЕ К ИНТЕРНЕТУ . И да, это очень быстро. Спасибо. Отсюда и голос.
Roon13

9
Это решение работает не для всех устройств. Некоторые устройства всегда возвращают 2, как указано @Salmaan. Устройства, которые я тестировал, имели подключение к Интернету, и целью проверки связи является DNS-сервер Google, который отвечает на запросы проверки связи. Я думаю, что некоторые поставщики не разрешают пинг-запросы. Например, я тестировал на планшете Samsung 10.1 (4.3), и решение не работает. Когда я запускаю команду ping через утилиту командной строки, я получаю ошибку разрешения. Команда также не работает на эмуляторах. Будьте осторожны, используя это решение.
Эрен Йылмаз

9
Этот подход работает не на всех телефонах. Не получается, например, на Samsung Galaxy S3. Смотрите здесь: Почему ping работает на некоторых устройствах, а не на других?
Адиль Хуссейн,

1032

Если устройство находится в режиме полета (или, по-видимому, в других ситуациях, когда нет доступной сети), cm.getActiveNetworkInfo()будет null, поэтому вам нужно добавить nullпроверку.

Модифицировано ( решение Эдди ) ниже:

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

Также добавьте следующее разрешение AndroidManifest.xml:

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

Еще один маленький момент: если вам абсолютно необходимо сетевое соединение в данный момент времени, то лучше использовать netInfo.isConnected(), чем netInfo.isConnectedOrConnecting. Я думаю, что это зависит от индивидуального варианта использования.


109
ИМХО, вам все еще следует и нужно проверять наличие исключений тайм-аута http, поскольку могут быть ситуации, когда сеть подключена, но не будет действительного подключения к Интернету, потому что единственный способ получить к ней доступ, например, через VPN - таким образом, Например, соединение WI-FI, но нет фактического интернет-трафика. Другая ситуация - зависание сервера. Это две проблемы, которые я недавно запустил, и менеджер соединений здесь не поможет.
полночь

21
Я согласен с полуночью и Пинту, этот ответ не должен быть принятым, он не имеет никакого отношения к проверке, где вы находитесь в Интернете. Например, если телефон подключен к сети Wi-Fi с использованием портала портала, как в отеле, эта функция неправильно вернет значение true. Правильный ответ - пинговать сервер в общедоступном интернете.
Мигель

9
когда для моего роутера не работает интернет, если я подключаюсь к роутеру через wifi, то приведенный выше код возвращает true. Но это не должно быть, верно? Можете ли вы помочь мне
MoHaN K RaJ

5
Мне пришлось добавить контекст, context.getSystemServiceили он не работает. Я получил свою подсказку здесь androidhive.info/2012/07/…
Франциско Корралес Моралес

1
Хороший способ проверить доступность сети. Но как проверить доступ в интернет?
Тамас Болвари

296

Не нужно быть сложным. Самый простой и основополагающий способ - использовать ACCESS_NETWORK_STATEразрешение и просто подключить метод.

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

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

Вы также можете использовать, requestRouteToHostесли у вас есть конкретный хост и тип соединения (Wi-Fi / мобильный).

Вам также понадобится:

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

в вашем андроид манифесте.


82
Лучше сделать нулевую проверку на уровне cm.getActiveNetworkInfo (), чтобы он выбрасывал ноль, если активной сети не было.
Самуил

см stackoverflow.com/a/11691676/1979773 для более глубокого exaplanation о requestRouteToHost ()
Spartako

Мне пришлось добавить контекст, context.getSystemServiceили он не работает. Я получил свою подсказку здесь androidhive.info/2012/07/…
Франциско Корралес Моралес

9
Это решение вернет true, если вы подключены к точке доступа WiFi, даже если эта точка НЕ ​​имеет подключения к Интернету.
Джош


63

Чтобы приступить getActiveNetworkInfo()к работе, необходимо добавить в манифест следующее.

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

Этот должен быть определенно под правильным ответом (потраченное впустую слишком много времени, чтобы понять, что, черт возьми, неправильно).
Индрек Кюэ

2
Для этого не нужно разрешение ИНТЕРНЕТ, просто ACCESS_NETWORK_STATE. ИНТЕРНЕТ нужен только в том случае, если вы действительно подключаетесь к удаленным местам, а не запрашиваете состояние радиоприемника устройства.
Том

3
Ваш ответ в настоящее время на самом деле не является ответом, это лишь относительно небольшое дополнение к другим ответам. Если бы все остальные ответы не были здесь, будет ли ваш ответ иметь смысл? На самом деле, нет. Потому что, если так, то лучше дополнить свой ответ кодом того, как его использовать, или удалите свой ответ и добавьте информацию в другом ответе (вы не потеряете репутацию)
Тим

Будьте осторожны, getActiveNetworkInfo()не рекомендуется использовать API уровня 29.
Переполнение стека

46

Посмотрите на класс ConnectivityManager. Вы можете использовать этот класс для получения информации об активных соединениях на хосте. http://developer.android.com/reference/android/net/ConnectivityManager.html

РЕДАКТИРОВАТЬ: Вы можете использовать

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

или

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

и проанализировать перечисление DetailState возвращенного объекта NetworkInfo

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ: Чтобы узнать, можете ли вы получить доступ к хосту, вы можете использовать

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

Очевидно, я использую Context.getSystemService (Context.CONNECTIVITY_SERVICE) в качестве прокси, чтобы сказать

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

Не уверен, но это похоже на код, чтобы проверить, какое сетевое подключение я в данный момент. Например, я на WiFi, нет никакой гарантии, что ваш домашний Wi-Fi маршрутизатор подключен к интернету ... чтобы проверить, действительно ли вам нужно сделать запрос к интернет-
серверу

1
В разделе РЕДАКТИРОВАНИЕ произошла ошибка, я пропустил запрос requestRouteToHost (). Перечитайте ответ сейчас :)
Чинмай Канчи

requestRouteToHost устарел.
Джахазиил

46

проверь этот код ... у меня сработало :)

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

Затем я определяю обработчик:

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

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

        } else { // code if connected

        }   
    }
};

... и запустить тест:

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

3
Что гугл не работает? Для этого также требуется разрешение ИНТЕРНЕТ, которое не требуется для данной задачи. Наконец, это потребляет данные (даже если они незначительны). Это просто похоже на такой клуг.
Том

28
@ Честно говоря, это, пожалуй, единственный правильный ответ. Другие примеры просто показывают, доступно ли сетевое соединение и / или есть ли соединение с этой сетью, но не отвечают на вопрос, может ли эта сеть на самом деле также установить удаленное соединение (например, с веб-сайтом). Так что это отвечает на плакаты Q, а другие ответы нет
slinden77

2
@dmmh Да, это, к сожалению, правда из того, что я видел с API-интерфейсами Android. Возможно, простой пинг мог бы быть лучше, stackoverflow.com/questions/3905358/… . Если вы действительно обеспокоены, вы можете даже включить список IP-адресов для пинга, потому что, хотя вероятность того, что Google когда-нибудь закроется, очень мала, вероятность того, что Google, Bing и Yahoo будут отключены в тот же день, еще меньше. , Просто мои мысли.
Том

10
Нет смысла делать эту проверку. Если вы собираетесь тратить системное время и сетевые ресурсы на подключение к Google, вы могли бы потратить их вместо подключения к ресурсу, который вам действительно нужен.
Бенджамин

16
В Китае гугл заблокировали !!
Anthone

26

Найден и изменен (!) По этой ссылке :

В своем файле манифеста добавьте как минимум:

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

Возможно, у вас уже есть разрешение на доступ в Интернет, если вы обращаетесь к нему. Тогда логическая функция, которая позволяет проверять наличие соединения:

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

Я сделал этот код, он самый простой и просто логический. спрашиваяif(isOnline()){

Вы получаете, если есть соединение и если он может подключиться к странице код состояния 200(стабильное соединение).

Обязательно добавьте правильные INTERNETи ACCESS_NETWORK_STATEразрешения.

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
Возможно, вам следует заменить 200 на HttpURLConnection.HTTP_OK
Yash

5
Что делать, если Google не работает?
Яурав Гадав

12

Это работает для меня:

Чтобы проверить доступность сети:

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

Чтобы проверить доступ в интернет:

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

Это отличное решение для проверки работоспособности сервера. Спасибо!
Williew

1
isOnline () вообще не должен запускаться в основном потоке, как будто есть сигнал Wi-Fi, но нет интернета, это займет слишком много времени и заблокирует основной поток.
сумасшедший

9

Там больше, чем один способ

Во-первых, самый короткий, но неэффективный способ

Требуется только разрешение состояния сети

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

Тогда этот метод,

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

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

        return isConnected;

    }

Как видно в ответах ConnectivityManager , это решение, я просто добавил его в методе, это упрощенный метод, который все используют,
ConnectivityManagerвозвращает значение true, если есть доступ к сети, а не доступ к Интернету, то есть если ваш WiFi подключен к маршрутизатору, но у маршрутизатора нет Интернета, то это возвращает true, проверяет наличие соединения

Во-вторых, эффективный способ

Состояние сети и интернет-разрешения необходимы

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

Тогда этот класс,

 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
            }

        }


    }

Вызов CheckInternetAsyncTask

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

Некоторые объяснения: -

  • Вы должны проверить интернет AsyncTask, в противном случае он может бросить android.os.NetworkOnMainThreadExceptionв некоторых случаях

  • ConnectivityManager используется для проверки доступа к сети, если true отправляет запрос (Ping)

  • Запрос на отправку http://clients3.google.com/generate_204, Этот известный URL-адрес, как известно, возвращает пустую страницу с HTTP-статусом 204, это быстрее и эффективнее, чем http://www.google.com, прочитайте это . если у вас есть веб-сайт, то предпочтительнее размещать свой веб-сайт вместо Google, только если вы используете его в приложении

  • Время ожидания может быть изменено (20 мс -> 2000 мс), обычно используется 1500 мс


2
Отличный вопрос, грустно, у вас нет больше очков. Это должен быть правильный ответ.
Джон Фреди Трухильо Ортега

Я новичок в Android. тем не менее, это хорошо освещенный ответ, и он привлекает больше внимания @ 7569106
Mazen Embaby

1
лучший и полный ответ, спасибо. если у кого-то есть уведомление на веб-сайте, этому условию должно нравиться это urlc.getResponseCode () == 200 и не нужно проверять urlc.getContentLength () == 0
AREF

твой второй вариант
терпит

это замораживает приложение
нафики ахмед

8

Из всего, что я видел до сих пор, самый короткий и чистый путь должен быть:

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: Это не пингует какой-либо хост, он просто проверяет состояние соединения, поэтому, если у вашего роутера нет подключения к интернету и ваше устройство подключено к нему, этот метод вернет true, хотя у вас нет интернета.
Для реального теста я бы порекомендовал выполнить запрос HttpHead (например, на www.google.com) и проверить статус, если его 200 в порядке, все в порядке и ваше устройство подключено к Интернету.


Я хотел поместить этот метод в глобальный класс, поэтому мне пришлось использовать эту версию, чтобы я мог передать контекст из действия, из которого я вызывал его. Спасибо!
RyanG

8

Вот метод, который я использую:

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

Еще лучше проверить, что он «подключен»:

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

Вот как использовать метод:

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

Требуется разрешение:

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

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


7

Один важный случай использования на мобильных устройствах, чтобы убедиться, что фактическое соединение существует. Это общая проблема, когда мобильный пользователь входит в сеть Wifi с «Captive Portal», в который ему необходимо войти. Я использую эту функцию блокировки в фоновом режиме, чтобы убедиться, что соединение существует.

/*
 * 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 за фактическую проверку сквозного подключения. Однако для ситуации «Captive Portal» я обнаружил, что многие из них пройдут вышеуказанный тест, даже если вы не выполнили вход - вы получите страницу входа и ответ 200 независимо от того, какой URL вы запрашиваете. Поэтому я пытаюсь открыть страницу в своем собственном домене, которая, как мне известно, не существует, и убедиться, что я получаю 404. Кроме того, вы можете перейти на известную существующую страницу, убедиться, что вы получите 200, и проверить содержимое, которое возвращается, чтобы убедиться, что это то, что вы ожидаете.
GreyBeardedGeek

6

Вы можете перебрать все сетевые подключения и проверить, есть ли хотя бы одно доступное подключение:

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

Для меня не было хорошей практикой проверять состояние соединения в классе Activity, потому что

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

должен быть вызван там, или вам нужно передать ваш экземпляр Activity (контекст) в класс обработчика соединения, чтобы можно было там проверить состояние соединения. Когда нет доступного соединения (wifi, сеть), я ловлю исключение 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();
}

Таким образом, я могу обработать этот случай вместе с другими случаями в том же классе (мой сервер всегда отвечает обратно строкой json)


6

Это работает для меня. Попробуйте это.

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

Этот ответ не может работать сейчас, так как мы не можем получить доступ к сети в основном потоке сейчас.
布鞋 白 布鞋

1
Я имею в виду с уровня API 11, это не работает. Причина: developer.android.com/reference/android/os/… . Если это работает для вас, это означает, что вы запускаете этот код на старом устройстве Android. (до ГБ).
布鞋 白 布鞋

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder () .permitAll (). Build (); StrictMode.setThreadPolicy (политика); Добавьте эти две строки в вашу программу для исключения исключений из основного потока сети
selva_pollachi

Хорошо, я не должен говорить, что это не может работать, я должен сказать, что это может работать (в зависимости от целевой старой версии или настройки Strictmode), но не рекомендуется. Это может легко вызвать ANR. (При такой высокой конфигурации тайм-аута в httpurlconnection)
布鞋 白 布鞋

да .. ты прав .. просто я поставил это, потому что это тоже один из способов.
selva_pollachi

6

Этот метод дает вам возможность для очень быстрого метода (для обратной связи в реальном времени) или более медленного метода (для однократных проверок, которые требуют надежности)

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

Я использую этот код вместо 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();
    }

Было бы замечательно, если бы вы пояснили, означает ли IOException отсутствие подключения к Интернету и насколько надежным оно может быть.
Милад.Нозари

5

Нетрудно проверить состояние сети Android / интернет-соединения. Следующий DetectConnectionкласс поможет вам проверить этот статус:

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

Для получения более подробной информации посетите Как проверить состояние сети Android / подключения к Интернету


5

Лучший подход:

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

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

1
Мне нравится этот подход, но я должен указать на некоторые вещи. isReachable () возвращает логическое значение, поэтому вместо возврата true в разделе try вы можете сделать это как boolean connected = InetAddress.getByName ("google.com"). isReachable (3); затем вернитесь на связь. Кроме того, isReacheable генерирует исключения IOException и IllegalArgumentException, поэтому будет хорошей идеей заменить UnknownHostException на IllegalArgumentException и включить третий catch: catch (Exception E).
Яша

2
Но тогда isReachable использует ICMP, для которого могут потребоваться привилегии суперпользователя, и использует порт 7, который обычно не имеет запущенных служб в последних системах. Поэтому лучший способ проверить маршрут к онлайн-сервису - это обычный TCP; следовательно, голосование против.
Яш

5

Ниже приведен код из моего Utilsкласса:

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

}

Как и все остальные, которые не прочитали проблему, это не решает проблему, так как не проверяет соединение с Интернетом. Подключение к локальной точке доступа Wi-Fi вернет true, даже если точка доступа не позволит вам подключиться к Интернету.
Педро Помбейро,

5

Вы можете использовать этот метод для определения доступности сети

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

Я применил решение, предоставленное @Levit, и создал функцию, которая не будет вызывать дополнительный запрос Http.

Это решит ошибку 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;
}

Теперь назовите это как,

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

4

Это описано в документации для Android http://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html


1
Но описанный там метод на самом деле не проверяет соединение с Интернетом, он просто проверяет, установлено ли соединение (есть ли у него доступ в интернет или нет). Название этого официального документа действительно вводит в заблуждение.
Tiago

2
Дать ответ на вопрос лучше, чем просто разместить ссылку на информацию. Что делать, если ссылка не работает? У нас не будет ответа.
Хосе Llausas

4

Я просмотрел все ответы и нашел свой собственный ответ, который сначала проверяет, доступен ли Интернет и доступен ли он, а затем проверяет, активен он или нет.

Я включил все необходимые методы и классы для проверки активного подключения к Интернету.

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

Вы можете проверить, активен ли Интернет, используя следующий код:

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

Лучше запакуйте потоки в вашем NetworkUtils и, следовательно, «заставьте» разработчика не злоупотреблять вашим методом
Ewoks

Удалить одно лишнее условие. if ((NetworkUtils.isInternetActiveWithPing () == NetworkUtils.STATUS_CONNECTED) || NetworkUtils.isInternetActiveWithInetAddress ()) {// Do Network Operation} else {// Сообщение об ошибке}
Джавад Зеб

4

Очень важно проверить, есть ли у нас связь с isAvailable () и возможно ли установить соединение с 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();
}

и вы можете определить тип активной сети WiFi :

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

или мобильный 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;
}

не забудьте разрешения:

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

Хорошая сводка компонентов подключения устройства, просто нужно обернуть их в инструкции try / catch, чтобы избежать сбоев. Точно так же, просто делайте свои обычные вызовы HttpURLConnection, пока они связаны с обработкой ошибок, вы скоро узнаете, есть ли у вас подключение к интернету
rangi

4

Котлин и сопрограммы

Я поместил функцию в ViewModel, который имеет viewModelScope. Используя наблюдаемое, LiveDataя информирую деятельность о связи.

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

Деятельность

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

3

Просто создайте следующий класс, который проверяет подключение к интернету:

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

Этот класс просто содержит метод, который возвращает логическое значение состояния соединения. Поэтому, если говорить простым языком, если метод находит допустимое соединение с Интернетом, возвращаемое значение равно true, иначе, falseесли действительное соединение не найдено.

Следующий метод в MainActivity затем вызывает результат из ранее описанного метода и предлагает пользователю действовать соответствующим образом:

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.");
        }
    }

В приведенном выше коде, если результат ложный (поэтому нет подключения к Интернету, пользователь перенаправляется на панель Wi-Fi Android, где ему предлагается подключиться к точке доступа Wi-Fi).


3

Обновление 29/06/2015 Если вы используете Xamarin.Android и хотите проверить подключение, вы можете использовать пакет Nuget, который предоставит вам эту функциональность на нескольких платформах. Хорошие кандидаты здесь и здесь . [Конец обновления]

Приведенные выше ответы довольно хороши, но все они на Java, и почти все они проверяют наличие соединения. В моем случае мне нужно было соединение с определенным типом соединения, и я работаю на Xamarin.Android. Более того, я не передаю ссылку на контекст моей деятельности на аппаратном уровне, я использую контекст приложения. Так что вот мое решение, если кто-то придет сюда с похожими требованиями. Я не прошел полное тестирование, но обновлю ответ, как только я закончу тестирование

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
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.