Обнаружение, если у устройства Android есть подключение к Интернету

Мне нужно указать, подключено ли у моего устройства подключение к Интернету или нет. Я нашел много ответов, например:

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

(Взято из Определите, есть ли доступ к Интернету на Android.)

Но это неправильно, например, если я подключен к беспроводной сети, у которой нет доступа к Интернету, этот метод вернет true... Есть ли способ сказать если устройство имеет подключение к Интернету, а не если оно связано только с чем-то?

Ответ 1

Вы правы. Код, который вы предоставили, проверяет только наличие сетевого подключения. Лучший способ проверить, есть ли активное интернет-соединение, - попытаться подключиться к известному серверу через http.

public static boolean hasActiveInternetConnection(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
            urlc.setRequestProperty("User-Agent", "Test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 200);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(LOG_TAG, "No network available!");
    }
    return false;
}

Конечно, вы можете подставить URL http://www.google.com для любого другого сервера, к которому хотите подключиться, или сервер, который, как вы знаете, имеет хорошую работоспособность.

Как сказал Тони Чо в этом комментарии ниже, убедитесь, что вы не запускаете этот код в основном потоке, иначе вы получите исключение NetworkOnMainThread (в Android 3.0 или новее). Вместо этого используйте AsyncTask или Runnable.

Если вы хотите использовать google.com, вы должны посмотреть на модификацию Jeshurun. В его ответе он изменил мой код и сделал его более эффективным. Если вы подключаетесь к

HttpURLConnection urlc = (HttpURLConnection) 
            (new URL("http://clients3.google.com/generate_204")
            .openConnection());

а затем проверьте код ответа для 204

return (urlc.getResponseCode() == 204 && urlc.getContentLength() == 0);

вам не нужно сначала загружать всю домашнюю страницу google.

Ответ 2

Я немного изменил ответ THelper, чтобы использовать известный хак, который Android уже использует, чтобы проверить, имеет ли подключенная сеть WiFi доступ в Интернет. Это намного эффективнее, чем захват всей домашней страницы Google. Подробнее см. здесь и здесь.

public static boolean hasInternetAccess(Context context) {
    if (isNetworkAvailable(context)) {
        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();
            return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
        } catch (IOException e) {
            Log.e(TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(TAG, "No network available!");
    }
    return false;
}

Ответ 3

public boolean isInternetWorking() {
    boolean success = false;
    try {
        URL url = new URL("https://google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(10000);
        connection.connect();
        success = connection.getResponseCode() == 200;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return success;
}

возвращает true, если интернет действительно доступен

Убедитесь, что у вас есть эти два разрешения

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

Ответ 4

Если вы нацеливаете Lollipop или выше, можно использовать новый класс NetworkCapabilities, например:

public static boolean hasInternetConnection(final Context context) {
    final ConnectivityManager connectivityManager = (ConnectivityManager)context.
            getSystemService(Context.CONNECTIVITY_SERVICE);

    final Network network = connectivityManager.getActiveNetwork();
    final NetworkCapabilities capabilities = connectivityManager
            .getNetworkCapabilities(network);

    return capabilities != null
            && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}

Ответ 5

Вам не обязательно создавать полное HTTP-соединение. Вы можете попробовать просто открыть TCP-соединение с известным хостом, и если вам удастся подключиться к Интернету.

public boolean hostAvailable(String host, int port) {
  try (Socket socket = new Socket()) {
    socket.connect(new InetSocketAddress(host, port), 2000);
    return true;
  } catch (IOException e) {
    // Either we have a timeout or unreachable host or failed DNS lookup
    System.out.println(e);
    return false;
  }
}

Затем просто установите флажок:

boolean online = hostAvailable("www.google.com", 80);

Ответ 6

Основываясь на принятых ответах, я построил этот класс со слушателем, чтобы вы могли использовать его в основном потоке:

Первый: класс InterntCheck, который проверяет подключение к Интернету в фоновом режиме, затем вызывает метод слушателя с результатом.

public class InternetCheck extends AsyncTask<Void, Void, Void> {


    private Activity activity;
    private InternetCheckListener listener;

    public InternetCheck(Activity x){

        activity= x;

    }

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


        boolean b = hasInternetAccess();
        listener.onComplete(b);

        return null;
    }


    public void isInternetConnectionAvailable(InternetCheckListener x){
        listener=x;
        execute();
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager) activity.getSystemService(CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null;
    }
    private boolean hasInternetAccess() {
        if (isNetworkAvailable()) {
            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();
                return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.d("TAG", "No network available!");
        }
        return false;
    }

    public interface InternetCheckListener{
        void onComplete(boolean connected);
    }

}

Второй: создайте экземпляр класса в основном потоке и дождитесь ответа (если вы работали с Firebase api для android, прежде чем это вам будет знакомо!).

new InternetCheck(activity).isInternetConnectionAvailable(new InternetCheck.InternetCheckListener() {

        @Override
        public void onComplete(boolean connected) {
           //proceed!
        }
    });

Теперь внутри метода onComplete вы получите, подключено ли устройство к Интернету или нет.

Ответ 7

попробуйте этот

public class ConnectionDetector {
    private Context _context;

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

    public boolean isConnectingToInternet() {
        if (networkConnectivity()) {
            try {
                HttpURLConnection urlc = (HttpURLConnection) (new URL(
                        "http://www.google.com").openConnection());
                urlc.setRequestProperty("User-Agent", "Test");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(3000);
                urlc.setReadTimeout(4000);
                urlc.connect();
                // networkcode2 = urlc.getResponseCode();
                return (urlc.getResponseCode() == 200);
            } catch (IOException e) {
                return (false);
            }
        } else
            return false;

    }

    private boolean networkConnectivity() {
        ConnectivityManager cm = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            return true;
        }
        return false;
    }
}

вы должны добавить в файл манифеста следующие разрешения:

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

Затем вызовите так:

if((new ConnectionDetector(MyService.this)).isConnectingToInternet()){
    Log.d("internet status","Internet Access");
}else{
    Log.d("internet status","no Internet Access");
}

Ответ 8

private static NetworkUtil mInstance;
private volatile boolean mIsOnline;

private NetworkUtil() {
    ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
    exec.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            boolean reachable = false;
            try {
                Process process = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
                int returnVal = process.waitFor();
                reachable = (returnVal==0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            mIsOnline = reachable;
        }
    }, 0, 5, TimeUnit.SECONDS);
}

public static NetworkUtil getInstance() {
    if (mInstance == null) {
        synchronized (NetworkUtil.class) {
            if (mInstance == null) {
                mInstance = new NetworkUtil();
            }
        }
    }
    return mInstance;
}

public boolean isOnline() {
    return mIsOnline;
}

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

Ответ 9

Самый последний способ сделать это из документации - это использовать ConnectivityManager для запроса активной сети и определения ее подключения к Интернету.

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

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

Добавьте эти два разрешения в свой файл AndroidManifest.xml:

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

Ответ 10

Проверьте тип Wi-Fi в диспетчере подключений:

   //check network connection
    ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    boolean hasNetworkConnection = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    System.out.println("Connection ? : " + hasNetworkConnection);
    //check wifi
    boolean hasWifiConnection = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
    System.out.println("Wifi ? : " + hasWifiConnection);

Документация Android описывает "TYPE_WIFI" как "подключение для передачи данных WIFI". Устройства могут поддерживать более одного.