Как проверить доступ в интернет на 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 ]

8 голосов
/ 26 декабря 2017

Есть более чем один способ

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

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

<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 мс

8 голосов
/ 19 сентября 2012

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

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 OK все в порядке и на вашем устройстве есть интернет подключение.

7 голосов
/ 13 июня 2013

Один важный вариант использования на мобильных устройствах, обеспечивающий фактическое соединение. Это обычная проблема, когда мобильный пользователь входит в сеть 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;
}
6 голосов
/ 25 ноября 2012

Для меня не было хорошей практикой проверять состояние соединения в классе 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 голосов
/ 25 июля 2012

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

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());
}}
6 голосов
/ 13 февраля 2012

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

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;
}
5 голосов
/ 24 октября 2013
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();
}

}
5 голосов
/ 09 января 2017

Я применил решение, предоставленное @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
}
5 голосов
/ 11 июня 2013

Ниже приведен код из моего 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 голосов
/ 18 июля 2012

Нетрудно проверить состояние сети 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 / подключения к Интернету

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