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.