Android, A Complete Course, From Basics to Enterprise Edition

Gérer le Wifi

Android, A Complete Course, From Basics to Enterprise Edition. 1

Gérer le Wifi 1

Communiquer avec le système. 1

1.1         Gérer les connexions wifi 1

 Cet article est extraie du livre « Android, A Complete Course », disponible sur Android2ee.com.

Les exemples ou les programmes présents dans cet ouvrage sont fournis pour illustrer les descriptions théoriques. Ce code est libre de toute utilisation mais n'est pas distribuable.

La distribution du code est reservée au site :

http://android2ee.com.

La propriété intellectuelle du code appartient à :

Mathias Séguy

L’utilisation de ces codes est sous votre unique responsabilité et personne d’autre que vous ne pourra être tenu responsable des préjudices ou dommages de quelques natures que ce soit pouvant résulter de son utilisation.

Tous les noms de produits ou marques cités dans cet ouvrage sont des marques déposés par leurs propriétaires respectifs.

Publié par http://android2ee.com

Titre Original : Android, A Complete Course, From Basics to Enterprise Edition. Édition Française.

ISBN : 979-10-90388-00-0

Copyright © 2011 by Mathias Séguy

 

Aucune représentation ou reproduction, même partielle, autre que celles prévues à l’article L. 122-5 2° et 3° a) du code de la propriété intellectuelle ne peut être faite sans l’autorisation expresse de Mathias Seguy ou, le cas échéant, sans le respect des modalités prévues à l’article L. 122-10 dudit code

Communiquer avec le système

1.1       Gérer les connexions wifi

1.1.1       Gestion des réseaux Wifi

1.1.1.1       Connaître les états des réseaux Wifi et écouter leurs changements

Les informations associées au réseau wifi sont :

·         Son état (Enable, enabling, disabling, disabled, unknown)

·         Les informations sur sa connexion (son adresse mac, IP, sa vitesse, le ssid du réseau et la force du signal)

Ensuite vous pouvez vous abonner à l’écoute des changements :

·         Des états de la connexion

·         Des états du supplicant (plus fin que les états de la connexion) qui est l’état de l’établissement de la connexion à un point d’accès.

·         De la valeur du RSSI, la force du signal

·         De l’état de la connexion wifi (perte ou récupération de la connexion)

·         De l’identifiant du réseau

Il ne faut pas écouter tout ces états, certains s’incluant les uns les autres, d’autres se simplifiant. Nous montrons dans l’exemple ci-dessous comment utiliser et écouter tous ces changements d’états, vous laissant le choix de l’évènement à écouter.

/** * The Wifi Manager */

WifiManager wifiManager;

/* * (non-Javadoc) *  * @see android.app.Activity#onCreate(android.os.Bundle) */

@Override

protected void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                // First Instanciate the Wifi and Connectivity Managers:

                wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

                // Browse wifi networks and retrieve their parameters

                browseWifiNetworks();

}

/************************************************************************************/

/** Browsing the WIFI networks **********************************************************/

/************************************************************************************/

/** * Browse wifi network and detect their parameters */

private void browseWifiNetworks() {

                // Managing wifi state

                wifiManager.isWifiEnabled();

                switch (wifiManager.getWifiState()) {

                case WifiManager.WIFI_STATE_ENABLING:

                case WifiManager.WIFI_STATE_ENABLED:

                case WifiManager.WIFI_STATE_DISABLING:

                case WifiManager.WIFI_STATE_DISABLED:

                case WifiManager.WIFI_STATE_UNKNOWN:

                               break;

                }

                // Retrieveing active wifi informations

                WifiInfo wifiInfo = wifiManager.getConnectionInfo();

                // Basic Service Set Identifier is null if no connection available

                if (wifiInfo.getBSSID() != null) {

                               String macAdress = wifiInfo.getMacAddress();

                               int ipAddress = wifiInfo.getIpAddress();

                               int linkSpeed = wifiInfo.getLinkSpeed();// in WifiInfo.LINK_SPEED_UNITS

                               String ssid = wifiInfo.getSSID();

                               int signalStrenght = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 5);

                }

                // Listening for WIFI changes

                registerReceiver(wifiChangesBroadCastReceiver, new IntentFilter(

                                               WifiManager.WIFI_STATE_CHANGED_ACTION));

                registerReceiver(wifiChangesBroadCastReceiver, new IntentFilter(

                                               WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));

                registerReceiver(wifiChangesBroadCastReceiver, new IntentFilter(

                                               WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION));

                registerReceiver(wifiChangesBroadCastReceiver, new IntentFilter(

                                               WifiManager.RSSI_CHANGED_ACTION));

                registerReceiver(wifiChangesBroadCastReceiver, new IntentFilter(

                                               WifiManager.NETWORK_STATE_CHANGED_ACTION));

                registerReceiver(wifiChangesBroadCastReceiver, new IntentFilter(

                                               WifiManager.NETWORK_IDS_CHANGED_ACTION));

}

/** Listening for WIFI changes */

/** ---------------------------------- */

/** * Define the brodcast receiver that listen for connectivty changes */

private BroadcastReceiver wifiChangesBroadCastReceiver = new BroadcastReceiver() {

  @Override

  public void onReceive(Context context, Intent intent) {

    final String action = intent.getAction();

    // insure you are listening for the right intent

    // The WIFI State changed listening:Wi-Fi has been enabled, disabled, enabling,

    // disabling, or unknown

    if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {

      // Check the current Wifi Stat (you can also retrieve the EXTRA_WIFI_PREVIOUS_STATE

      switch (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,

          WifiManager.WIFI_STATE_UNKNOWN)) {

      case WifiManager.WIFI_STATE_ENABLING:// Do something

      case WifiManager.WIFI_STATE_ENABLED:// Do something

      case WifiManager.WIFI_STATE_DISABLING:// Do something

      case WifiManager.WIFI_STATE_DISABLED:// Do something

      case WifiManager.WIFI_STATE_UNKNOWN:// Do something

        break;

      }

    }

    // The Supplicant State changed:the state of establishing a connection to an access

    // point has changed

    else if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {

      SupplicantState supplicantstate = (SupplicantState) intent

          .getParcelableExtra(WifiManager.EXTRA_NEW_STATE);

      switch (supplicantstate) {

      case UNINITIALIZED:

        // no wpa_supplicant

      case SCANNING:

        // Scanning for a network

      case ASSOCIATING:

        // Trying to associate with a BSS/SSID.

      case ASSOCIATED:

        // Association completed.

This state is entered when the driver reports that association has been successfully completed with an AP. If IEEE 802.1X is used (with or without  WPA/WPA2), wpa_supplicant remains in this state until the IEEE 802.1X/EAPOL  authentication has been completed.

      case COMPLETED:

        // All authentication completed.

 This state is entered when the full authentication process is completed. In case of WPA2, this happens when the 4-Way Handshake is successfully completed. With WPA, this state is entered after the Group Key Handshake;  with IEEE 802.1X (non-WPA) connection is completed after dynamic keys arereceived (or if not used, after the EAP authentication has been completed). With static WEP keys and plaintext connections, this state is entered when an association has been completed.  This state indicates that the supplicant has completed its processing for the association phase and that data connection is fully configured. Note, however, that there may not be any IP address associated with the connection yet. Typically, a DHCP request needs to be sent at this point to obtain an address.

      case FOUR_WAY_HANDSHAKE:

        // WPA 4-Way Key Handshake in progress.

This state is entered when WPA/WPA2 4-Way Handshake is started.  In case of WPA-PSK, this happens when receiving the first EAPOL-Key frame after association. In case of WPA-EAP, this state is entered when the IEEE  802.1X/EAPOL authentication has been completed.

      case GROUP_HANDSHAKE:

        // WPA Group Key Handshake in progress.

This state is entered when 4-Way Key Handshake has been completed (i.e., when the supplicant sends out message 4/4) and when Group Key rekeying is started by the AP (i.e., when supplicant receives message 1/2).

      case DORMANT:

        // An Android-added state that is reported when a client issues an explicit  DISCONNECT command.

In such a case, the supplicant is not only dissociated from the current access point (as for the DISCONNECTED state above), but it also does not attempt to connect to any access point until a RECONNECT or REASSOCIATE command is issued by the client.

      case DISCONNECTED:

        // This state indicates that client is not associated, but is likely to start looking for an access point. This state is entered when a connection is lost.

      case INACTIVE:

        // Inactive state (wpa_supplicant disabled).

This state is entered if there are no enabled networks in the configuration.  wpa_supplicant is not trying to associate with a new network and external  interaction (e.g., ctrl_iface call to add or enable a network) is needed to  start association

      case INVALID:

        // A pseudo-state that should normally never be seen.

        break;

      }

      // Detect a supplicant error

      if (intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0) = =

WifiManager.ERROR_AUTHENTICATING) {

        // Do something

      }

    }

    // A connection to the supplicant has been established (and it is now possible to

    // perform Wi-Fi operations) or the connection to the supplicant has been lost

    else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {

      // The lookup key for a boolean that indicates whether a connection to the

      // supplicant daemon has been gained or lost. true means a connection now exists.

      if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) {

        // A connection now exist, do something

      } else {

        // A connection has been lost, do something

      }

    }

    // The RSSI (signal strength) has changed.

    else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {

      int newRSSI = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, 0);

      // handle the newRSSI identification key (the network changed its id)

    }

    // The state of Wi-Fi connectivity has changed

    else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {

      NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);

      // Do something with this new Network information

      if (networkInfo.isConnected() && intent.hasExtra(WifiManager.EXTRA_BSSID)) {

        // The lookup key for a String giving the BSSID of the access point to which we

        // are connected.

        String newBSSID = intent.getStringExtra(WifiManager.EXTRA_BSSID);

      }

    }

    // The network IDs of the configured networks could have changed

    else if (action.equals(WifiManager.NETWORK_IDS_CHANGED_ACTION)) {

      // You should update your access point

    }

  }

};

 

1.1.1.2       Scanner les Hot Spot Wifi et se connecter à l’un d’eux

Pour scanner les Hot Spots Wifi, il faut d’abord enregistrer un BroadCastReceiver comme écouteur de l’intention SCAN_RESULTS_AVAILABLE_ACTION  et récupérer la liste des nouveaux réseaux trouvés dans l’attribut scanResults du WifiManager. Quand l’évènement est écouté par le BroadCastReceiver, cette liste est chargée dans le WifiManager.

La liste des ScanResult peut-être parcourue pour obtenir des informations sur les nouveaux réseaux (BSSID, SSID, Capabilities, fréquence du signal et force de celui-ci). Elle peut aussi être utilisée pour enrichir la liste des réseaux Wifi disponible pour l’établissement d’une connexion. Les réseaux disponibles étant enregistrés en tant qu’instance de l’objet WifiConfiguration et peuvent être obtenus par la méthode getConfiguredNetworks du WifiManager.

Pour se connecter à l’une de ces configurations (et donc à l’un de ces réseaux) il faut utiliser la méthode enableNetwork du WifiManager.

 

/** * The Wifi Manager */

WifiManager wifiManager;

/* * (non-Javadoc) *  * @see android.app.Activity#onCreate(android.os.Bundle) */

@Override

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    // First Instanciate the Wifi and Connectivity Managers:

    wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

    // Browse wifi networks and retrieve their parameters

    browseWifiNetworks();

}

/*****************************************************************************************/

/** Browsing the WIFI networks **********************************************************/

/*****************************************************************************************/

/** * Browse wifi network and detect their parameters */

private void browseWifiNetworks() {

    // Scan the hotspot around

    registerWifiScannerBroadcastReceiver();

    wifiManager.startScan();

    // Set the usage of a specific wifi network

    connectToWifiSpot();

}

/** Scan the hotspot around */

/** ----------------------------- */

/** * Register the broadcast to listen to End of Wifi Scan */

private void registerWifiScannerBroadcastReceiver() {

    registerReceiver(wifiScannerBroadCastReceiver, new IntentFilter(

            WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

}

 

/** * Define the brodcast receiver that listen for connectivty changes */

private BroadcastReceiver wifiScannerBroadCastReceiver = new BroadcastReceiver() {

    @Override

    public void onReceive(Context context, Intent intent) {

        final String action = intent.getAction();

        // insure you are listening for the right intent

        if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {

            // The scan is over, you can browse the results

            manageWifiScanResults();

        }

    }

};

 

/** * Manage the Results of the Wifi Scan */

private void manageWifiScanResults() {

    List<ScanResult> scanResults = wifiManager.getScanResults();

    List<String> results = new ArrayList<String>();

    for (ScanResult scanResult : scanResults) {

        // adress of the access point

        String bssid = scanResult.BSSID;

        // Describes the authentication, key management, and encryption schemes supported by the

        // access point.

        String capabilities = scanResult.capabilities;

        if (capabilities.contains("WEP")) {            // WEP security

        } else if (capabilities.contains("WAP")) {            // WAP security

        } else if (capabilities.contains("WAP2")) {            // WaP2 security

        } else if (capabilities.contains("Open")) {            // No security

        } else if (capabilities.contains("PSK")) {            // PSK ??

        } else if (capabilities.contains("EAP")) {            // EAP for entreprise

        } else {            // No security        }

        // The frequency in MHz of the channel over which the client is communicating with the

        // access point.

        int frequency = scanResult.frequency;

        // The network name.

        String ssid = scanResult.SSID;

        // The detected signal level in dBm.

        int level = scanResult.level;

        results.add(String .format(

"New Wifi Spot : (SSID =%s, BSSID=%s, Capabilities = %s, frequency %i, level %i)",

ssid, bssid, capabilities, frequency, level));

    }

    addResultsToConfiguredNetworks(scanResults);

}

 

/** * Add the hotSpot found in the WifiConfiguration *

 * @param results the list of ScanResult to add to the WifiConfiguration */

private void addResultsToConfiguredNetworks(List<ScanResult> results) {

    // List of already configured hotspot

    List<WifiConfiguration> wifiConfigurations = wifiManager.getConfiguredNetworks();

    // List of ssid of the already configured hotspot

    List<String> ssidConfigured = new ArrayList<String>();

    // Fill that list with ssid of the already configured hotspot

    for (WifiConfiguration wifiConfiguration : wifiConfigurations) {

        ssidConfigured.add(wifiConfiguration.SSID);

    }

    // The new configuration to add built using ScanResult and the associated networkId

    WifiConfiguration newWifiConf;

    int newNetworkId;

    // Browse the Scan result

    for (ScanResult result : results) {

        if (ssidConfigured.contains(result.SSID)) {

            // Do nothing hotSpot already configured

        } else {

            // You can here ask the user if he wants to add the current ScanResult of the loop

            // if he agrees run the following lines, else skip them

            // Add this hot spot to the WifiConfiguration

            newWifiConf = new WifiConfiguration();

            newWifiConf.BSSID = result.BSSID;

            newWifiConf.SSID = result.SSID;

            newWifiConf.hiddenSSID = false;

            newWifiConf.priority = 1;

            newNetworkId = wifiManager.addNetwork(newWifiConf);

            if (newNetworkId < 0) {

                Toast.makeText(this, String.format("Unable to add SSID:%s", result.SSID),

                        Toast.LENGTH_LONG).show();

            }

            // if you want to connect to a network use this id (newNetworkId)

            // cf the method connectTo WifiSpot

        }

    }

}

/** Connect to a hotspot around */

/** ----------------------------------- */

/** * Choose a random WifiConfiguration and connect to it */

private void connectToWifiSpot() {

    // List of already configured hotspot

    List<WifiConfiguration> wifiConfigurations = wifiManager.getConfiguredNetworks();

    if (!wifiConfigurations.isEmpty()) {

            //Set the disable All others (to be sure that only your network will be used for connection as your network

            //will be the only one enabled)

            boolean disableOthers = true;

            //Select the network you want to connect to using the WifiConfiguration

            WifiConfiguration selectedWifiConf = wifiConfigurations.get(0);

            //Ask for enabling this network connection

            Boolean success = wifiManager.enableNetwork(selectedWifiConf.networkId, disableOthers);

            //test if you request succeded

            if (!success) {

                Toast.makeText(

                        this,

                        String.format("Unable to enable the network (SSID:%s, networkId:%i)",

                                selectedWifiConf.SSID, selectedWifiConf.networkId),

                        Toast.LENGTH_LONG).show();

            }    }

}