Как определить, что в Android установлено WIFI-соединение?


142

Мне нужно определить, есть ли у меня подключение к сети через WIFI. Какая трансляция отправляется, чтобы установить, что установлено действительное сетевое соединение. Мне нужно убедиться, что существует допустимое сетевое соединение для HTTP. Что я должен слушать и какие дополнительные тесты мне нужно сделать, чтобы узнать, существует ли действительное соединение.


Здесь я нашел ответы на некоторые части этого вопроса: stackoverflow.com/questions/4238921/…
— Androider

1
Но все еще остается вопрос, КОГДА проверять эти условия?
— Androider

1
Я хотел бы получить отзывы о том, будут ли происходить трансляции, которые могут быть пойманы приемником трансляции?
— Androider

1
Как я могу сделать это на Android O, поскольку приемники неявного вещания, такие как android.net.wifi.STATE_CHANGE, больше не смогут быть зарегистрированы в манифесте (см. Developer.android.com/guide/components/… ). Если мы зарегистрируем его в активности приложения (скажем, onCreate), то его придется отменить в onStop (), и мы больше не будем получать события, связанные с Wi-Fi,
— zafar142003

Ответы:


127

Вы можете зарегистрировать, 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();
}

1
Почему SUPPLICANT_CONECTION_CHANGE_ACTION? Я думал, что это просто трансляция изменения CONNECTION_CHANGE. Почему СЛАДКА ??? спасибо
— Androider

2
а? Я не вижу действия с именем connection_change ...? Я вижу только изменение состояния Wi-Fi, но это действие только указывает, включен ли Wi-Fi (или включение / отключение), а не подключен ли он ... supplicant_connection_change_action не делает то, что вам нужно?
— jpm

9
Для меня WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION не работает в случае, если соединение с известной Wi-Fi станцией было установлено / потеряно. Но WifiManager.NETWORK_STATE_CHANGED_ACTION действительно работает.
— Яр

1
"android.net.wifi.STATE_CHANGE" работал у меня. проверьте мой ответ ниже
— М. Усман Хан

1
«Конечно, перед этим вы должны проверить, подключено ли устройство к Wi-Fi». - Итак, чтобы получить начальное состояние Wi-Fi, вы можете использовать этот метод ...private boolean isConnectedViaWifi() { ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return mWifi.isConnected(); }
— ban-geoengineering

106

Лучшее, что сработало для меня:

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"/>

1
Я думаю, что это лучший ответ на конкретное изменение состояния Wi-Fi. Спасибо
— Mikel

4
Для удобства использования в будущем это жестко запрограммированное действие - WifiManager.NETWORK_STATE_CHANGED_ACTION .
— Anonsage

3
if (info! = null && info.isConnected ()) = без спагетти.
— gswierczynski

1
нам нужно написать какой-либо код для отправки трансляции в основной деятельности ??
— Нисари Балакришнан

1
Как я могу сделать это на Android O, поскольку приемники неявного вещания, такие как android.net.wifi.STATE_CHANGE, больше не смогут быть зарегистрированы в манифесте (см. Developer.android.com/guide/components/… ). Если мы зарегистрируем его в активности приложения (скажем, onCreate), то его нужно будет отменить в onStop (), и мы больше не будем получать события, связанные с Wi-Fi.
— zafar142003 03

18

У меня только 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
    }      
}

1
Для меня также работал только WifiManager.NETWORK_STATE_CHANGED_ACTION, какие-либо объяснения причины, почему только это будет работать?
— бенчук

11

Ответ пользователя @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"/>

1
что такое wifiState?
— behelit

1
Также хотел бы знать, что такое wifiState, как он был сгенерирован
— Эван Парсонс

1
@behelit теперь "wifiState" присутствует в отредактированном ответе.
— Yog Guru

8

Вы можете запустить 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);  

7

Чтобы определить состояние подключения 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: у меня отлично работает :)


1
К вашему сведению, с Android 6, когда у вас есть действующее соединение для передачи данных в ячейке, изменения в состоянии Wi-Fi не будут вызывать CONNECTIVITY_ACTION. Единственная причина, по которой они это сделали, - это повлияло на состояние подключения, теперь это не так.
— Брюс

5

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

1
Работает на устройствах с <API 26. Как предположил @Isham, это действие больше не поддерживается в Android O
— tiagocarvalho92

4

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, тогда отменяет запросы.


Есть ли способ запустить worker, даже если мое приложение принудительно завершено. Диспетчер работ работает с .setRequiredNetworkType (UNMETERED), только если приложение открыто. Есть ли способ вызвать работника, даже если приложение убито (принудительное закрытое состояние). Потому что неявный широковещательный приемник тоже несколько ограничен. Что будет лучшей альтернативой?
— Суреш

3

Вот пример моего кода, который учитывает предпочтения пользователей разрешать связь только при подключении к 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;
}

3

У меня есть два метода обнаружения 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();
}

Как я могу сделать это на Android O, поскольку приемники неявного вещания, такие как android.net.wifi.STATE_CHANGE, больше не смогут быть зарегистрированы в манифесте (см. Developer.android.com/guide/components/… ). Если мы зарегистрируем его в активности приложения (скажем, onCreate), то его нужно будет отменить в onStop (), и мы больше не будем получать события, связанные с Wi-Fi
— zafar142003

2

Я использовал этот код:

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
                    }
                }
            }
        };
    }


2

1) Я также пробовал подход Broadcast Receiver, хотя я знаю, что CONNECTIVITY_ACTION / CONNECTIVITY_CHANGE устарело в API 28 и не рекомендуется. Также привязан к использованию явного регистра, он прослушивает, пока приложение работает.

2) Я также попробовал Firebase Dispatcher, который работает, но не за пределами приложения.

3) Рекомендуемый найденный способ - WorkManager, чтобы гарантировать выполнение за пределами убитого процесса и внутренне с помощью registerNetworkRequest ()

Самым большим доказательством в пользу подхода №3 является сам документ Android . Специально для приложений, работающих в фоновом режиме.

Также здесь

В Android 7.0 мы удаляем три часто используемых неявных трансляции - CONNECTIVITY_ACTION, ACTION_NEW_PICTURE и ACTION_NEW_VIDEO - поскольку они могут разбудить фоновые процессы сразу нескольких приложений и нагружать память и батарею. Если ваше приложение получает их, воспользуйтесь преимуществами Android 7.0 для перехода на JobScheduler и связанные с ним API.

Пока у нас все работает с использованием Periodic WorkManager request.

Обновление: в итоге я написал об этом средний пост из 2 серий .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.