Android,
A Complete Course, From
Basics to Enterprise Edition
Android, A Complete Course, From Basics to Enterprise
Edition
1.1 Gérer les connexions réseau
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 :
La
propriété intellectuelle du code appartient à :
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
Il y a deux types de connexions différentes : le network « mobile » et le wifi. Chacun possède ses propres méthodes et sa propre gestion.
Tout d’abord, dès que votre application doit communiquer avec internet, vous devez vous assurer de la préférence utilisateur concernant le transfert de données en tache de fond. En d’autre terme si votre activité est en pause, peut-elle continuer à utiliser le réseau. Si ce n’est pas le cas, vous ne devez en aucun cas l’utiliser.
Dans ce chapitre, nous expliquerons :
· Comment connaitre la préférence réseau Wifi ou réseau mobile de l’utilisateur,
· comment parcourir les réseaux mobiles et récupérer leurs informations,
· comment parcourir les réseaux wifi, scanner ces réseaux et se connecter à l’un d’eux,
· enfin comment écouter les changements d’états de changement de connexion à un réseau.
Les objets principaux de la manipulation des réseaux sont :
· Le ConnectivtyManager pour gérer l’ensemble des réseaux,
· Le NetworkInfo qui porte les informations associées à un réseau
· Le WifiManager pour gérer les réseaux WIFI,
· Le WifiInfo qui porte les informations associées à un réseau Wifi
· Le ScanResult qui porte les informations associées à un réseau WIFI découvert suite à un scan de réseau Wifi
· Le WifiConfiguration qui porte les informations associées aux réseaux Wifi déjà configurés sur l’appareil
Enfin pour pouvoir manipuler ces paramètres réseaux, il faut demander les permissions suivantes dans votre manifest.xml :
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
Il y a deux types de préférences, le droit d’utiliser le réseau en tâche de fond et la préférence du réseau à utiliser.
Pour cela vous devez instancier le
ConnectivityManager et récupérer le paramètre getBackgroundDataSetting. Si
celui-ci est à faux, vous pouvez demander à l’utilisateur de changer ses
préférences. Pour cela afficher lui un message lui demandant de le faire puis
écouter le changement de préférence. Comme d’habitude cette écoute s’appuie sur
la déclaration d’un BroadCastReceiver et l’enregistrement de ce receiver à
l’intention
ACTION_BACKGROUND_DATA_SETTING_CHANGED.
Le code ci-dessous montre comment si prendre :
/** * The connectivity Manager (for
network) */
ConnectivityManager connectivityManager;
/* * (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:
connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//
Then detect user preference for network usage
//
Do i have the right to use network in background (when my activty is hidden)
Boolean networkUsedInBackground = connectivityManager.getBackgroundDataSetting();
//
If you really need the exchange data in background using the network, ask user:
if (!networkUsedInBackground) {
//
Instanciate the state changed listening using broadcast
registerbackgroundExchangeOnNetWorkBroadcastReceiver();
//
Ask user to change its pereferences
Toast.makeText(
this,
"Could
you please change your preference for network usage "
+ "(Parameter>Account And syncronization>BackgroundData
parameters)",
Toast.LENGTH_SHORT).show();
//
normally you should wait the user to change its preference using a
// while(atomicBoolean userChangeItsPrference)
//
or use a toast display a message with a yes||no
}
}
/*******************************************************************************/
/**
Asking user to exchange data in background using the network
*************************/
/********************************************************************************/
/** * Define the brodcast receiver that listen
for background network usage */
private BroadcastReceiver backgroundExchangeOnNetWorkBroadCastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//
Find the cuurent state (you can also call EXTRA_PREVIOUS_STATE for the previous
//
state)
if (connectivityManager.getBackgroundDataSetting()) {
//
the user change its preferences
} else {
//
the user doesn't want you to use network in background, that's all
//
You then can kill your activity or find a workaround
}
//
anyway, the answer is given
unregisterReceiver(backgroundExchangeOnNetWorkBroadCastReceiver);
}
};
/** * To be call when asking the user to change
its preference */
private void
registerbackgroundExchangeOnNetWorkBroadcastReceiver() {
//
register the previous BroadCast associated to the Intent Action State Changed
registerReceiver(backgroundExchangeOnNetWorkBroadCastReceiver, new IntentFilter(
ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED));
}
La méthode getNetworkPreference de l’objet ConnectivityManager est à utiliser :
/** * The connectivity Manager (for
network) */
ConnectivityManager connectivityManager;
/* * (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:
connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//
Browse user preferences
browseUserPreference();
}
/************************************************************************************/
/** Managing User preference
***********************************************************/
/**********************************************************************************/
/**
Browse user preferences */
private void browseUserPreference() {
switch (connectivityManager.getNetworkPreference()) {
case ConnectivityManager.TYPE_WIFI:
case ConnectivityManager.TYPE_MOBILE:
break;
}
//
And you can set the prefernce you want:
connectivityManager.setNetworkPreference(ConnectivityManager.TYPE_WIFI);
}
Pour récupérer l’ensemble des réseaux et leurs informations il faut appeler la méthode getAllNetworkInfo de l’objet ConnectivityManager. Cette méthode renvoie un ensemble de networkInfo qui porte les informations du réseau associé. Les informations principales sont décrites dans le code ci-dessous.
Pour écouter les changements d’états de la connexion réseau, l’utilisation d’un BroadCastReceiver et son enregistrement en tant qu’écouteur de l’événement CONNECTIVITY_ACTION est à utiliser.
Le code ci-dessous présente ces deux aspects :
/** * The connectivity Manager (for network) */
ConnectivityManager
connectivityManager;
/* * (non-Javadoc) * * @see
android.app.Activity#onCreate(android.os.Bundle) */
@Override
protected void
onCreate(Bundle savedInstanceState) {
// Browse mobile networks and retrieve their parameters
browseMobileNetworks();
// And Listen for Network state changed
registerConnectivityStateChanged();
}
/**************************************************************************************/
/** Browsing the Mobile networks **********************************************************/
/**************************************************************************************/
/** * Browse network and detect their parameters */
private void
browseMobileNetworks() {
// retireve all the networks around
NetworkInfo[] networksInfo = connectivityManager.getAllNetworkInfo();
// Network Info
NetworkInfo netWorkInfo;
// Network type and subtype
int
networkType;
// network state
NetworkInfo.State state;
for (int i =
0; i < networksInfo.length;
i++) {
netWorkInfo =
networksInfo[i];
// Retrieve network type
networkType =
netWorkInfo.getType();
if (networkType ==
ConnectivityManager.TYPE_MOBILE) {
// The different possible states for your network
state
= netWorkInfo.getState();
switch
(netWorkInfo.getState()) {
case CONNECTING:
case CONNECTED:
case SUSPENDED:
case DISCONNECTING:
case DISCONNECTED:
case UNKNOWN:
break;
}
// Others states vision:
netWorkInfo.isAvailable();
netWorkInfo.isConnected();
netWorkInfo.isConnectedOrConnecting();
netWorkInfo.isFailover();
netWorkInfo.isRoaming();
} else {
// others connections can be WIFI
networkType
= ConnectivityManager.TYPE_WIFI;
// Cial Up Networking bridge
networkType
= ConnectivityManager.TYPE_MOBILE_DUN;
// High Priority Mobile Data Connection
networkType
= ConnectivityManager.TYPE_MOBILE_HIPRI;
// Multi Media Messaging Service
networkType
= ConnectivityManager.TYPE_MOBILE_MMS;
// Secure User Plane Location
networkType
= ConnectivityManager.TYPE_MOBILE_SUPL;
}
}
}
/***********************************************************************************/
/** Listen for connectivity changes
*******************************************************/
/***********************************************************************************/
/** * Define the brodcast receiver that listen for connectivty changes
*/
private
BroadcastReceiver connectivityChangesBroadCastReceiver = 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(ConnectivityManager.CONNECTIVITY_ACTION)) {
// Is there a connectivity?
boolean
noConnectivity = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
// Is there a change in the connection from the
prefered network to this one
boolean
isFailover = intent.getBooleanExtra(
ConnectivityManager.EXTRA_IS_FAILOVER,
false);
// Retrieve networkInfo
NetworkInfo
currentNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
ConnectivityManager.EXTRA_NETWORK_INFO);
// This is supplied when there is another network that
it may be possible to connect
// to.
NetworkInfo
otherNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
// string that indicates why an attempt to connect to
a network failed
String
failureReason = intent.getStringExtra(
ConnectivityManager.EXTRA_REASON);
// string that provides optionally supplied extra
information about the network
// state
String
extraInformations = intent.getStringExtra(
ConnectivityManager.EXTRA_EXTRA_INFO);
}
}
};
/** And Listen for Connectivty state changed */
private void
registerConnectivityStateChanged() {
// register the previous BroadCast associated to the
Intent Action Connectivity Changed
registerReceiver(connectivityChangesBroadCastReceiver, new IntentFilter(
ConnectivityManager.CONNECTIVITY_ACTION));
}