Le Wi-Fi sous Android

Acesyde

Nous allons voir dans ce tutoriel comment utiliser l'API WiFi d'Android.

Commentez

- Titre : Le Wi-Fi sous Android

- Auteur : Acesyde

- Parution : 23 novembre 2012

- Mise à jour : 11 février 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1. Prérequis

- 2. Permissions

- 3. Ressources

- 4. Implémentation

- 5. Conclusion

- 6. Annexes

- 7. Remerciements

- 8. Liens

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 :

<?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 :

<?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 :

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 :

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.

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 :

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

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

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 :

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.

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

Tutoriel d'origine sur ace-art.fr