Эффективный способ проверить медленное подключение к Интернету и отличить сетевое подключение от фактического подключения к Интернету в Android.

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

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


person akg    schedule 14.08.2014    source источник
comment
NetworkInfo сообщит вам, что устройство каким-то образом подключено к какой-то сети. Затем вы можете попробовать, например. чтобы загрузить веб-страницу Google, чтобы проверить, есть ли у вас доступ в Интернет.   -  person Wildcopper    schedule 14.08.2014
comment
@Wildcopper-Но что, если интернет-соединение слишком медленное? Должен ли я добавить тайм-аут в мой фоновый поток?   -  person akg    schedule 14.08.2014


Ответы (2)


Если вы хотите знать, когда у вас есть активное подключение к Интернету, сделайте что-то вроде этого:

Некоторые статические переменные:

/**
 * Set the number of retries when reestablishing Internet connection.
 */
private static int retryConnectionNumber = 0;

/**
 * The maximum number of retries allowed for Internet connection.
 */
private final static int CONNECTION_RETRY_MAX = 5;

/**
 * The timeout of the HTTP request when checking for Internet connection.
 */
private final static int REQUEST_TIMEOUT = 2000;

Способ проверки доступности сети:

private static void isNetworkAvailable(final Handler handler,
            final int timeout) {
        new Thread() {
            private boolean responded = false;

            @Override
            public void run() {
                URL url = null;
                try {
                    url = new URL("http://your_server_addres.com");
                } catch (MalformedURLException e1) {
                    e1.printStackTrace();
                }
                String host = "";
                if (null != url) {
                    host = url.getHost();
                }

                Log.i("NetworkCheck", "[PING] host: " + host);
                Process process = null;
                try {
                    process = new ProcessBuilder()
                            .command("/system/bin/ping", "-c 1",
                                    "-w " + (timeout / 1000), "-n", host)
                            .redirectErrorStream(true).start();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                InputStream in = process.getInputStream();
                StringBuilder s = new StringBuilder();
                int i;

                try {
                    while ((i = in.read()) != -1) {
                        s.append((char) i);

                        if ((char) i == '\n') {
                            Log.i("NetworkCheck",
                                    "[PING] log: " + s.toString());
                            if (s.toString().contains("64 bytes from")) {
                                // If there were a response from the server at
                                // all, we have Internet access
                                responded = true;
                            }
                            s.delete(0, s.length());
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    // Destroy the PING process
                    process.destroy();

                    try {
                        // Close the input stream - avoid memory leak
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    // Send the response to the handler, 1 for success, 0
                    // otherwise
                    handler.sendEmptyMessage(!responded ? 0 : 1);
                }
            }
        }.start();
    }

Обработчик:

/**
 * Handler used that receives the connection status for the Internet.
 * If no active Internet connection will retry #CONNECTION_RETRY_MAX times
 */
private static Handler listenForNetworkAvailability = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if (msg.what != 1) { // code if not connected
            Log.i("NetworkCheck", "not connected");

            if (retryConnectionNumber <= CONNECTION_RETRY_MAX) {
                Log.i("NetworkCheck", "checking for connectivity");
                Here you could disable & re-enable your WIFI/3G connection before retry

                // Start the ping process again with delay
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        isNetworkAvailable(listenForNetworkAvailability, REQUEST_TIMEOUT);
                    }
                }, 5000);
                retryConnectionNumber++;
            } else {
                Log.i("NetworkCheck", "failed to establish an connection");
                // code if not connected
            }
        } else {            
            Log.i("NetworkCheck", "connected");
            retryConnectionNumber = 0;
            // code if connected
        }
    }
}
person Ionut Negru    schedule 14.08.2014

Что-то вроде этого будет работать:

private boolean haveNetworkConnection() {
        boolean haveConnectedWifi = false;
        boolean haveConnectedMobile = false;

        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();
        for (NetworkInfo ni : netInfo) {
            if (ni.getTypeName().equalsIgnoreCase("WIFI"))
                if (ni.isConnected())
                    haveConnectedWifi = true;
            if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
                if (ni.isConnected())
                    haveConnectedMobile = true;
        }
        return haveConnectedWifi || haveConnectedMobile;
    }

Я скопировал этот код из здесь ( Я понимаю код - я просто добавляю код сюда для удобства пользователя + мне сказал администратор, что вы должны сделать это и указать исходный пост). Лично я бы разделил это на две функции: одну для мобильных устройств и одну для Wi-Fi, но выбор за вами.

person apmartin1991    schedule 14.08.2014
comment
@ apmartin1991-этот код все равно будет возвращать значение true при наличии сети, но без Интернета. Приложение все равно будет падать. - person akg; 14.08.2014
comment
isConnected() Указывает, существует ли сетевое соединение и возможно ли устанавливать соединения и передавать данные. Если у вас произошел сбой, то это может быть сбой по другой причине. Можете ли вы опубликовать свой logcat, чтобы мы могли просмотреть его, пожалуйста? - person apmartin1991; 14.08.2014
comment
@ apmartin1991-проблема в том, что я не могу создать это условие по своему желанию. Иногда, когда нет доступа в Интернет при подключении к Wi-Fi, приложение вылетает. - person akg; 14.08.2014