1. Prérequis

Voici les prérequis pour ce tutoriel :

  • projet Android 2.2 ;
  • un téléphone/tablette ;
  • un/plusieurs réseaux Wi-Fi ;
  • avoir lu le tutoriel sur les listviews.

2. Permissions

Notre projet nécessite quelques permissions :

  • android.permission.ACCESS_WIFI_STATE ;
  • android.permission.CHANGE_WIFI_STATE.

La première sert à checker l'état du Wi-Fi, la seconde à changer celui-ci.

3. Ressources

Je vous donne directement les ressources nécessaires pour l'adapter sans les expliquer, c'est pour cela qu'il faut se référencer au tutoriel sur les listviews si jamais vous ne comprenez pas.

Le format des items pour notre listview :

 
Sélectionnez
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="horizontal" android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <TextView android:layout_height="fill_parent" android:layout_width="10dp" android:background="@android:color/white" android:id="@+id/ForceSignal"/>

   <LinearLayout android:orientation="vertical"
       android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="10dp">

       <TextView android:id="@+id/tvWifiName" android:layout_width="fill_parent"
           android:layout_height="wrap_content" android:text="AP Name" />

       <TextView android:id="@+id/tvWifiMac" android:layout_width="fill_parent"
           android:layout_height="wrap_content" android:textSize="10dp"
           android:text="00:00:00:00:00:00" />

   </LinearLayout>

</LinearLayout>

Notre main.xml :

 
Sélectionnez
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
   <Button android:id="@+id/buttonRefresh" android:text="Rechercher" android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
   <ListView android:id="@+id/listViewWifi" android:layout_height="fill_parent" android:layout_width="match_parent"></ListView>
</LinearLayout>

La classe représentant notre item pour la listview :

 
Sélectionnez
public class WifiItem {
   private String APName;
   private String AdresseMac;
   private int ForceSignal;

   public String getAPName() {
       return APName;
   }
   public void setAPName(String aPName) {
       APName = aPName;
   }
   public String getAdresseMac() {
       return AdresseMac;
   }
   public void setAdresseMac(String adresseMac) {
       AdresseMac = adresseMac;
   }
   public int getForceSignal() {
       return ForceSignal;
   }
   public void setForceSignal(int forceSignal) {
       ForceSignal = forceSignal;
   }  

}

Notre adapter :

 
Sélectionnez
public class WifiAdapter extends BaseAdapter {

   private List<WifiItem> listeWifiItem;
   private LayoutInflater layoutInflater;

   public WifiAdapter(Context context, List<WifiItem> objects) {

           listeWifiItem = objects;
           layoutInflater = LayoutInflater.from(context);
   }

   public int getCount() {
       return listeWifiItem.size();
   }

   public Object getItem(int position) {
       return listeWifiItem.get(position);
   }

   public long getItemId(int position) {
       return position;
   }

   private class ViewWifiHolder {
       TextView tvApName;
       TextView tvAdresseMac;
       TextView ForceSignal;
   }

   public View getView(int position, View convertView, ViewGroup parent) {
       ViewWifiHolder viewHolder;

       if(convertView == null) {
           viewHolder = new ViewWifiHolder();

           convertView = layoutInflater.inflate(R.layout.item_wifi, null);

           viewHolder.tvApName = (TextView) convertView.findViewById(R.id.tvWifiName);
           viewHolder.tvAdresseMac = (TextView) convertView.findViewById(R.id.tvWifiMac);
           viewHolder.ForceSignal = (TextView) convertView.findViewById(R.id.ForceSignal);

           convertView.setTag(viewHolder);
       } else {
           viewHolder = (ViewWifiHolder)convertView.getTag();
       }

       // On affecte les valeurs
       viewHolder.tvApName.setText(listeWifiItem.get(position).getAPName());
       viewHolder.tvAdresseMac.setText(listeWifiItem.get(position).getAdresseMac());

       // On change la couleur en fonction de la force du signal
       if(listeWifiItem.get(position).getForceSignal() <= -80) {
           viewHolder.ForceSignal.setBackgroundColor(Color.GREEN);
       } else if(listeWifiItem.get(position).getForceSignal() <= -50) {
           viewHolder.ForceSignal.setBackgroundColor(Color.YELLOW);
       } else {
           viewHolder.ForceSignal.setBackgroundColor(Color.RED);
       }

       return convertView;
   }

}

4. Implémentation

Passons désormais à l'implémentation de notre code, tout d'abord nous allons commencer par instancier tous les objets dont nous avons besoin.

 
Sélectionnez
private Button boutonRechercher;
private ListView listeViewWifi;
private List<WifiItem> listeWifiItem;
private WifiAdapter wifiAdapter;
private WifiManager wifiManager;
private WifiBroadcastReceiver broadcastReceiver;
  • Le bouton de l'IHM.
  • La listview de l'IHM.
  • La liste des WifiItems.
  • Notre adapter.
  • Le WiFi Manager du sdk Android.
  • Le broadcast receiver que nous allons créer par la suite.

Notre méthode onCreate :

 
Sélectionnez
@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);

   listeViewWifi = (ListView) findViewById(R.id.listViewWifi);
   boutonRechercher = (Button) findViewById(R.id.buttonRefresh);

   boutonRechercher.setOnClickListener(new OnClickListener() {

       public void onClick(View v) {
           if(wifiManager != null)
               wifiManager.startScan();
       }
   });

   // On récupère le service WiFi d'Android
   wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);

   // Gestion de la liste des AP WiFi (voir tuto sur les adapters et les
   // listviews)
   listeWifiItem = new ArrayList<WifiItem>();
   wifiAdapter = new WifiAdapter(this, listeWifiItem);
   listeViewWifi.setAdapter(wifiAdapter);

   // Création du broadcast Receiver
   broadcastReceiver = new WifiBroadcastReceiver();

   // On attache le receiver au scan result
   registerReceiver(broadcastReceiver, new IntentFilter(
           WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

}

On commence par récupérer le bouton et la listview, ensuite on va lier notre WiFi Manager au service Android grâce au getSystemService.

Continuons en initialisant la liste d'objets et l' « adapter ».

Pour finir on va instancier notre broadcast receiver et l'enregistrer pour qu'il soit appelé à chaque fois qu'un scan des réseaux Wi-Fi est fait.

 
Sélectionnez
// On arrête le receiver quand on met en pause l'application
@Override
protected void onPause() {
   unregisterReceiver(broadcastReceiver);
   super.onPause();
}

// On remet en route le receiver quand on revient sur l'application
@Override
protected void onResume() {
   registerReceiver(broadcastReceiver, new IntentFilter(
           WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
   super.onResume();
}

N'oublions pas ces deux parties qui permettent d'arrêter de recevoir les scans si vous avez mis l'application en arrière-plan et de nouveau recevoir les scans si vous revenez sur celle-ci.

Pour terminer on fait des getters sur certaines de nos variables pour qu'elles soient accessibles dans le BroadcastReceiver.

 
Sélectionnez
public WifiManager getCurrentWifiManager() {
   return wifiManager;
}

public WifiAdapter getWifiAdapter() {
   return wifiAdapter;
}

public List<WifiItem> getListeWifiItem() {
   return listeWifiItem;
}

Passons maintenant à la création du BroadcastReceiver associé au Wi-Fi :

 
Sélectionnez
public class WifiBroadcastReceiver extends BroadcastReceiver {

    private WifiManager wifiManager;
    private WifiAdapter wifiAdapter;
    private List<WifiItem> listeWifiItem;

    @Override
    public void onReceive(Context context, Intent intent) {
        wifiManager = ((FormationWifiActivity) context).getCurrentWifiManager();
        wifiAdapter = ((FormationWifiActivity) context).getWifiAdapter();
        listeWifiItem = ((FormationWifiActivity) context).getListeWifiItem();

        // On vérifie que notre objet est bien instancié
        if (wifiManager != null) {

            // On vérifie que le WiFi est allumé
            if (wifiManager.isWifiEnabled()) {
                // On récupère les scans
                List<ScanResult> listeScan = wifiManager.getScanResults();

                // On vide notre liste
                listeWifiItem.clear();

                // Pour chaque scan
                for (ScanResult scanResult : listeScan) {
                    WifiItem item = new WifiItem();

                    item.setAdresseMac(scanResult.BSSID);
                    item.setAPName(scanResult.SSID);
                    item.setForceSignal(scanResult.level);

                    Log.d("FormationWifi", scanResult.SSID + " LEVEL "
                            + scanResult.level);

                    listeWifiItem.add(item);
                }

                // On rafraichit la liste
                wifiAdapter.notifyDataSetChanged();
            } else {
                Toast.makeText(context, "Vous devez activer votre WiFi",
                        Toast.LENGTH_SHORT);
            }
        }

    }

}
  • on crée une classe qui hérite de BroadcastReceiver ;
  • on redéfinit la méthode onReceive ;
  • on récupère nos getters de l'activité ;
  • on vérifie tout de même que le WiFi Manager est en route ;
  • on vérifie aussi que le Wi-Fi est activé ;
  • on récupère la liste des réseaux scannés ;
  • on vide notre liste et on la remplit avec les nouvelles informations ;
  • on spécifie à notre adapter que la liste a été modifiée.

5. Conclusion

Et voilà le tour est joué, normalement vous pouvez voir tous les réseaux Wi-Fi à portée de votre mobile.

Le broadcast receiver est appelé à chaque fois qu'un scan est fait par l'OS.

Image non disponible

6. Annexes

En espérant que ce tutoriel vous sera utile.

Source :  FormationWifi

7. Remerciements

Je tiens à remercier tout particulièrement Feanorin qui a mis ce tutoriel au format Developpez.com. 
Merci également à ClaudeLELOUP d'avoir pris le temps de le relire et de le corriger.

8. Liens