web-dev-qa-db-fra.com

Comment détecter quand la connexion WIFI a été établie dans Android?

J'ai besoin de détecter quand j'ai une connectivité réseau via WIFI. Quelle émission est envoyée pour établir qu'une connexion réseau valide a été établie. J'ai besoin de valider l'existence d'une connexion réseau valide pour HTTP. Qu'est-ce que je devrais écouter et quels tests supplémentaires dois-je effectuer pour savoir qu'une connexion valide existe.

131
Androider

Vous pouvez enregistrer un BroadcastReceiver pour être averti lorsqu'une connexion WiFi est établie (ou si la connexion a été modifiée).

Enregistrez le BroadcastReceiver:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(broadcastReceiver, intentFilter);

Et ensuite, dans votre BroadcastReceiver, faites quelque chose comme ceci:

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

Pour plus d'informations, voir la documentation sur BroadcastReceiver et WifiManager

Vous devez bien sûr vérifier si le périphérique est déjà connecté au WiFi auparavant.

EDIT: Grâce à ban-geoengineering, voici une méthode pour vérifier si le périphérique est déjà connecté:

private boolean isConnectedViaWifi() {
     ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE);
     NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);     
     return mWifi.isConnected();
}
119
jpm

Le meilleur qui a fonctionné pour moi:

AndroidManifest

<receiver Android:name="com.AEDesign.communication.WifiReceiver" >
   <intent-filter Android:priority="100">
      <action Android:name="Android.net.wifi.STATE_CHANGE" />
   </intent-filter>
</receiver>

Classe 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();
      }
   }
}

Les permissions

<uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE"/>
<uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE"/>
104
M. Usman Khan

Pour moi seulement WifiManager.NETWORK_STATE_CHANGED_ACTION fonctionne.

Enregistrer un récepteur de diffusion:

_IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
_

et recevez:

_@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
    }      
}
_
16
Yar

Les réponses données par l'utilisateur @JPM et @usman sont vraiment très utiles. Cela fonctionne bien, mais dans mon cas, il s'agit de onReceive plusieurs fois dans mon cas 4 fois, de sorte que mon code est exécuté plusieurs fois.

Je fais quelques modifications et fais selon mes besoins et maintenant il vient seulement 1 fois

Voici la classe Java pour la diffusion.

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

    }
}
}

dans 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"/>
10
Yog Guru

Vous pouvez établir une connexion Wi-Fi si vous donnez à l'utilisateur le choix de remplacer le comportement normal de demander à chaque fois.

J'ai choisi d'utiliser trois méthodes ...

public boolean isOnline() 
{
 ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
 NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
 return (networkInfo != null && networkInfo.isConnected());
}  

Il s’agit d’une vérification rapide s’il existe une connexion Internet Wifi ou CellData. De là, vous pouvez choisir l'action que vous voulez entreprendre. Est-ce en mode avion doit être vérifié aussi.

Sur un fil séparé. J'ai mis une variable IpAddress à = "" et interroge jusqu'à ce que j'ai une adresse IP valide.

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

Un autre extrait de code ... S'il n'est pas activé, activez-le (avec l'autorisation préalable des utilisateurs).

   if(wifi.isWifiEnabled()!=true)wifi.setWifiEnabled(true);  
8
user1445716

Pour détecter l’état de la connexion WIFI, j’ai utilisé CONNECTIVITY_ACTION de la classe ConnectivityManager pour:

    IntentFilter filter=new IntentFilter();
    filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    registerReceiver(receiver, filter);

et de votre 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: fonctionne bien pour moi :)

6
amine

Ce code ne nécessite aucune autorisation. Il est limité aux changements d'état de la connectivité du réseau Wi-Fi (aucun autre réseau n'est pris en compte). Le récepteur est publié de manière statique dans le fichier AndroidManifest.xml et n'a pas besoin d'être exporté car il sera appelé par le système protected broadcast , NETWORK_STATE_CHANGED_ACTION =, à chaque changement d'état de connectivité réseau.

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>
_

Classe 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();
    }
}
}
_

Autorisations:

_None
_
5
Codegateway

Android O a supprimé la possibilité de recevoir les émissions implicites en cas de changement d'état Wi-Fi. Donc, si votre application est fermée, vous ne pourrez pas les recevoir. Le nouveau WorkManager a la capacité de fonctionner lorsque votre application est fermée. Je l'ai donc expérimenté un peu et cela semble fonctionner assez bien:

Ajoutez ceci à vos dépendances:

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()
    }
}

N'oubliez pas qu'il s'agissait simplement d'un test rapide pour une notification ponctuelle. Il reste encore beaucoup à faire pour toujours être averti lorsque le WiFi est activé ou désactivé.

PS: Lorsque l'application est force quit, le travailleur n'est pas démarré, il semble que WorkManager annule les demandes à ce moment-là.

3
Marius

Voici un exemple de mon code, qui prend en compte la préférence des utilisateurs de n'autoriser que les communications lorsque connecté au Wifi.

J'appelle ce code de l'intérieur d'un IntentService avant d'essayer de télécharger des fichiers.

Notez que NetworkInfo sera null s'il n'y a aucune connexion réseau.

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;
}
2
Justin Phillips

J'ai deux méthodes pour détecter une connexion WIFI recevant le contexte de l'application:

1) mon ancienne méthode

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) ma nouvelle méthode (j'utilise actuellement cette méthode):

public boolean isConnectedWifi(Context context) {
         ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);     
         return networkInfo.isConnected();
}
2
Jorgesys

J'ai utilisé ce code:

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
Cuarcuiu

1) J'ai également essayé l'approche Récepteur de diffusion même si je sais que CONNECTIVITY_ACTION/CONNECTIVITY_CHANGE est obsolète dans l'API 28 et n'est pas recommandé. Egalement lié à l'utilisation d'un registre explicite, il écoute tant que l'application est en cours d'exécution.

2) J'ai aussi essayé Firebase Dispatcher qui fonctionne, mais pas au-delà de l'application tuée.

3) La solution recommandée est WorkManager pour garantir l'exécution au-delà du processus tué et en interne à l'aide de registerNetworkRequest ()

La plus grande preuve en faveur de l'approche n ° 3 est renvoyée par doc Android lui-même. Surtout pour les applications en arrière-plan.

Aussi ici

Dans Android 7.0, nous supprimons trois diffusions implicites couramment utilisées - CONNECTIVITY_ACTION, ACTION_NEW_PICTURE et ACTION_NEW_VIDEO - car elles permettent de réactiver les processus d'arrière-plan de plusieurs applications à la fois, d'alléger la mémoire et la batterie. Si votre application les reçoit, utilisez plutôt Android 7.0 pour migrer vers JobScheduler et les API associées.

Jusqu'à présent, cela fonctionne très bien pour nous en utilisant une requête Periodic WorkManager.

Mise à jour: j'ai fini par écrire 2 séries post moyen à ce sujet.

2
Wahib Ul Haq

Pour tous ceux qui profitent de CONNECTIVITY_CHANGE diffusion, veuillez noter que l'application n'est plus déclenchée lorsque l'application est en arrière-plan dans Android O.

https://developer.Android.com/about/versions/o/background.html

1
Isham