Обнаружение, если у устройства 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". Устройства могут поддерживать более одного.