Мне нужно определить, есть ли у меня подключение к сети через WIFI. Какая трансляция отправляется, чтобы установить, что установлено действительное сетевое соединение. Мне нужно убедиться, что существует допустимое сетевое соединение для HTTP. Что я должен слушать и какие дополнительные тесты мне нужно сделать, чтобы узнать, существует ли действительное соединение.
android
android-wifi
Андройдер
источник
источник
Ответы:
Вы можете зарегистрировать,
BroadcastReceiver
чтобы получать уведомления, когда соединение WiFi установлено (или если соединение изменилось).Зарегистрируйте
BroadcastReceiver
:IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); registerReceiver(broadcastReceiver, intentFilter);
А затем в вашем
BroadcastReceiver
сделать что-то вроде этого:@Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) { if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) { //do stuff } else { // wifi connection was lost } } }
Для получения дополнительной информации см. Документацию для
BroadcastReceiver
иWifiManager
Конечно, перед этим вы должны проверить, подключено ли устройство к WiFi.
РЕДАКТИРОВАТЬ: Благодаря ban-geoengineering вот способ проверить, подключено ли уже устройство:
private boolean isConnectedViaWifi() { ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return mWifi.isConnected(); }
источник
private boolean isConnectedViaWifi() { ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return mWifi.isConnected(); }
Лучшее, что сработало для меня:
AndroidManifest
<receiver android:name="com.AEDesign.communication.WifiReceiver" > <intent-filter android:priority="100"> <action android:name="android.net.wifi.STATE_CHANGE" /> </intent-filter> </receiver>
BroadcastReceiver класс
public class WifiReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); if(info != null && info.isConnected()) { // Do your work. // e.g. To check the Network Name or other info: WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); String ssid = wifiInfo.getSSID(); } } }
Разрешения
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
источник
У меня только
WifiManager.NETWORK_STATE_CHANGED_ACTION
работает.Зарегистрируйте широковещательный приемник:
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); registerReceiver(broadcastReceiver, intentFilter);
и получите:
@Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)){ NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); boolean connected = info.isConnected(); //call your method } }
источник
Ответ пользователя @JPM и @usman действительно очень полезен. Он работает нормально, но в моем случае это происходит
onReceive
несколько раз, в моем случае 4 раза, поэтому мой код выполняется несколько раз.Я делаю некоторые модификации и делаю согласно моим требованиям, и теперь это приходит только 1 раз
Вот класс Java для трансляции.
public class WifiReceiver extends BroadcastReceiver { String TAG = getClass().getSimpleName(); private Context mContext; @Override public void onReceive(Context context, Intent intent) { mContext = context; if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = cm.getActiveNetworkInfo(); if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI && networkInfo.isConnected()) { // Wifi is connected WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); String ssid = wifiInfo.getSSID(); Log.e(TAG, " -- Wifi connected --- " + " SSID " + ssid ); } } else if (intent.getAction().equalsIgnoreCase(WifiManager.WIFI_STATE_CHANGED_ACTION)) { int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN); if (wifiState == WifiManager.WIFI_STATE_DISABLED) { Log.e(TAG, " ----- Wifi Disconnected ----- "); } } } }
В AndroidManifest
<receiver android:name=".util.WifiReceiver" android:enabled="true"> <intent-filter> <action android:name="android.net.wifi.WIFI_STATE_CHANGED" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> </intent-filter> </receiver> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
источник
Вы можете запустить Wi-Fi-соединение, если дадите пользователю возможность переопределить нормальное поведение запроса каждый раз.
Я предпочитаю использовать три метода ...
public boolean isOnline() { ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); return (networkInfo != null && networkInfo.isConnected()); }
Это быстрая проверка, есть ли подключение к Интернету: Wi-Fi или CellData. Отсюда вы можете выбрать, какое действие вы хотите предпринять. Также необходимо проверить, находится ли он в режиме полета.
В отдельной ветке. Я устанавливаю для переменной IpAddress значение = "" и опрашиваю, пока не получу действующий IP-адрес.
WifiManager wifi; wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifi.getConnectionInfo(); int ipAddress = wifiInfo.getIpAddress(); String ip = null; ip = String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); Log.e(" >>IP number Begin ",ip);
Другой фрагмент кода ... Если он не включен, включите его (с предварительного разрешения пользователя)
if(wifi.isWifiEnabled()!=true)wifi.setWifiEnabled(true);
источник
Чтобы определить состояние подключения WIFI, я использовал CONNECTIVITY_ACTION из класса ConnectivityManager, поэтому:
IntentFilter filter=new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(receiver, filter);
и из вашего BroadCastReceiver:
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) { int networkType = intent.getIntExtra( android.net.ConnectivityManager.EXTRA_NETWORK_TYPE, -1); if (ConnectivityManager.TYPE_WIFI == networkType) { NetworkInfo networkInfo = (NetworkInfo) intent .getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); if (networkInfo != null) { if (networkInfo.isConnected()) { // TODO: wifi is connected } else { // TODO: wifi is not connected } } } }
ps: у меня отлично работает :)
источник
Этот код вообще не требует разрешения. Это ограничено только изменением состояния подключения к сети Wi-Fi (другие сети не учитываются). Приемник статически публикуется в файле AndroidManifest.xml и не должен быть экспортирован как она будет вызываться системой
protected broadcast
,NETWORK_STATE_CHANGED_ACTION
при каждом изменении состояния сети связи.AndroidManifest:
<receiver android:name=".WifiReceiver" android:enabled="true" android:exported="false"> <intent-filter> <!--protected-broadcast: Special broadcast that only the system can send--> <!--Corresponds to: android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION--> <action android:name="android.net.wifi.STATE_CHANGE" /> </intent-filter> </receiver>
Класс BroadcastReceiver:
public class WifiReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { /* Tested (I didn't test with the WPS "Wi-Fi Protected Setup" standard): In API15 (ICE_CREAM_SANDWICH) this method is called when the new Wi-Fi network state is: DISCONNECTED, OBTAINING_IPADDR, CONNECTED or SCANNING In API19 (KITKAT) this method is called when the new Wi-Fi network state is: DISCONNECTED (twice), OBTAINING_IPADDR, VERIFYING_POOR_LINK, CAPTIVE_PORTAL_CHECK or CONNECTED (Those states can be obtained as NetworkInfo.DetailedState objects by calling the NetworkInfo object method: "networkInfo.getDetailedState()") */ /* * NetworkInfo object associated with the Wi-Fi network. * It won't be null when "android.net.wifi.STATE_CHANGE" action intent arrives. */ NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); if (networkInfo != null && networkInfo.isConnected()) { // TODO: Place the work here, like retrieving the access point's SSID /* * WifiInfo object giving information about the access point we are connected to. * It shouldn't be null when the new Wi-Fi network state is CONNECTED, but it got * null sometimes when connecting to a "virtualized Wi-Fi router" in API15. */ WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); String ssid = wifiInfo.getSSID(); } } }
Разрешения:
None
источник
Android O удалил возможность получать неявные трансляции для изменения состояния Wi-Fi. Поэтому, если ваше приложение закрыто, вы не сможете их получить. У нового
WorkManager
есть возможность запускаться, когда ваше приложение закрыто, поэтому я немного поэкспериментировал с ним, и, похоже, он работает довольно хорошо:Добавьте это в свои зависимости:
implementation "android.arch.work:work-runtime:1.0.0-alpha08"
WifiConnectWorker.kt
class WifiConnectWorker : Worker() { override fun doWork(): Result { Log.i(TAG, "I think we connected to a wifi") return Result.SUCCESS } }
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) val workManager = WorkManager.getInstance() // Add constraint to start the worker when connecting to WiFi val request = OneTimeWorkRequest.Builder(WifiConnectWorker::class.java) .setConstraints(Constraints.Builder() .setRequiredNetworkType(UNMETERED) .build()) .build() // The worker should be started, even if your app is closed workManager.beginUniqueWork("watch_wifi", REPLACE, request).enqueue() } }
Имейте в виду, что это была всего лишь быстрая проверка одноразового уведомления. Чтобы всегда получать уведомления, когда Wi-Fi включается и выключается, нужно еще поработать.
PS: Когда приложение закрывается принудительно , рабочий не запускается, похоже
WorkManager
, тогда отменяет запросы.источник
Вот пример моего кода, который учитывает предпочтения пользователей разрешать связь только при подключении к Wi-Fi.
Я вызываю этот код изнутри,
IntentService
прежде чем попытаюсь загрузить материал.Обратите внимание, что
NetworkInfo
это будет,null
если нет какого-либо сетевого подключения.private boolean canConnect() { ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); boolean canConnect = false; boolean wifiOnly = SharedPreferencesUtils.wifiOnly(); NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); if(networkInfo != null) { if(networkInfo.isConnected()) { if((networkInfo.getType() == ConnectivityManager.TYPE_WIFI) || (networkInfo.getType() != ConnectivityManager.TYPE_WIFI && !wifiOnly)) { canConnect = true; } } } return canConnect; }
источник
У меня есть два метода обнаружения WIFI-соединения, получающего контекст приложения:
1) мой старый метод
public boolean isConnectedWifi1(Context context) { try { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); if (networkInfo != null) { NetworkInfo[] netInfo = connectivityManager.getAllNetworkInfo(); for (NetworkInfo ni : netInfo) { if ((ni.getTypeName().equalsIgnoreCase("WIFI")) && ni.isConnected()) { return true; } } } return false; } catch (Exception e) { Log.e(TAG, e.getMessage()); } return false; }
2) мой Новый метод (сейчас я использую этот метод):
public boolean isConnectedWifi(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return networkInfo.isConnected(); }
источник
Я использовал этот код:
public class MainActivity extends Activity { . . . @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); . . . } @Override protected void onResume() { super.onResume(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); registerReceiver(broadcastReceiver, intentFilter); } @Override protected void onPause() { super.onPause(); unregisterReceiver(broadcastReceiver); } private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) { if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) { // wifi is enabled } else { // wifi is disabled } } } }; }
источник
Для всех, кто любит трансляцию CONNECTIVITY_CHANGE , обратите внимание, что это больше не запускается, когда приложение находится в фоновом режиме в Android O.
https://developer.android.com/about/versions/o/background.html
источник
1) Я также пробовал подход Broadcast Receiver, хотя я знаю, что CONNECTIVITY_ACTION / CONNECTIVITY_CHANGE устарело в API 28 и не рекомендуется. Также привязан к использованию явного регистра, он прослушивает, пока приложение работает.
2) Я также попробовал Firebase Dispatcher, который работает, но не за пределами приложения.
3) Рекомендуемый найденный способ - WorkManager, чтобы гарантировать выполнение за пределами убитого процесса и внутренне с помощью registerNetworkRequest ()
Самым большим доказательством в пользу подхода №3 является сам документ Android . Специально для приложений, работающих в фоновом режиме.
Также здесь
Пока у нас все работает с использованием Periodic WorkManager request.
Обновление: в итоге я написал об этом средний пост из 2 серий .
источник