Как проверить доступ в интернет на Android? InetAddress никогда не истекает - PullRequest
617 голосов
/ 13 октября 2009

Я получил 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();
    }   
}

Ответы [ 51 ]

1018 голосов
/ 24 октября 2010

Если устройство находится в режиме полета (или, по-видимому, в других ситуациях, когда нет доступной сети), 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. Я думаю, что это зависит от индивидуального варианта использования.

472 голосов
/ 05 декабря 2014

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

  • 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 и т. Д.), Он блокируется некоторое время, если нет доступа в Интернет.

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

// 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 Пример (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 */}
292 голосов
/ 04 января 2010

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

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

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

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

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

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

в вашем манифесте Android.

63 голосов
/ 27 сентября 2010

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

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
46 голосов
/ 27 апреля 2011

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

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
45 голосов
/ 13 октября 2009

Посмотрите на класс 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) 

и синтаксический анализ подробного перечисления возвращенного объекта 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();
26 голосов
/ 11 января 2011

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

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

<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;
    }
}
15 голосов
/ 19 июля 2012

Я сделал этот код, он самый простой и просто логический. спрашивая 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;
}
12 голосов
/ 07 марта 2014

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

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

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;
}
8 голосов
/ 11 июля 2013

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...