11/08/2013 06:36:00 AM

La géolocalisation sous Android

LocationListener

Pour pouvoir géocaliser un utilisateur, il faut que vous possédiez une instance de la classe LocationListener ou que l’activité incluant votre carte implémente l’interface LocationListener. Nous allons opter pour la seconde solution et faire en sorte que la classe HelloGoogleMapActivity implémenter cette interface.
Ainsi afin de pouvoir s’abonner à la mise à jour des coordonnées de l’utilisateur, il faut utiliser la méthode requestLocationUpdates(String, long, float, LocationListener).
Cette méthode posséde 4 arguments :
  • Le provider utiliser pour recevoir les mises à jour des coordonnées utilisateurs (GPS / NETWORK …)
  • Un interval minimum entre deux notifications (en millisecondes)
  • Un interval minimum entre deux notifications (en metre)
  • L’instance de votre LocationListener
Il est conseillé de s’abonner aux mises à jour des coordonnées de l’utilisateur dans la méthode onResume et de se désabonner dans le méthode onStop afin de stopper l’utilisateur des ressources de localisation alors que l’application n’en a plus l’utilité.
Ce qui donnera :
@Override
protected void onResume() {
 super.onResume();
 lm = (LocationManager) this.getSystemService(LOCATION_SERVICE);
 if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER))
  lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, this);
 lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, this);
}

@Override
protected void onPause() {
 super.onPause();
 lm.removeUpdates(this);
}
Implémenter l’interface LocationListener équivaut à surchager les 4 méthodes suivantes :
  • OnProviderEnabled(String provider) : Cette méthode est appelée quand une source de localisation est activée (GPS, 3G..etc). L’argument représente le nom de la source activée. Vous pouvez par exemple vous abonner à la mise à jour de localisation via cette source. Ce qui donnera :
  • @Override
    public void onProviderEnabled(String provider) {
     String msg = String.format(getResources().getString(R.string.provider_enabled), provider);
     Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
    
    avec
    <string name="provider_enabled">The provider %s is now enabled</string>
  • OnProviderDisabled(String provider) : Cette méthode est appelée quand une source de localisation est désactivée(GPS, 3G..etc). L’argument est le nom de la source désactivée. Vous pouvez par exemple vous désabonner à la mise à jour de localisation via cette source. Ce qui donnera :
  • @Override
    public void onProviderDisabled(String provider) {
     String msg = String.format(getResources().getString(R.string.provider_disabled), provider);
     Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
    
    
    avec
    <string name="provider_disabled">The provider %s is now disabled</string>
  • OnStatusChanged(String provider, int status, Bundle extras) : Appeler quand le status d’une source change. Il existe 3 statuts (OUT_OF_SERVICE, TEMPORARILY_UNAVAILABLE, AVAILABLE). Ce qui donnera :
  • @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
     String newStatus = "";
     switch (status) {
      case LocationProvider.OUT_OF_SERVICE:
       newStatus = "OUT_OF_SERVICE";
       break;
      case LocationProvider.TEMPORARILY_UNAVAILABLE:
       newStatus = "TEMPORARILY_UNAVAILABLE";
       break;
      case LocationProvider.AVAILABLE:
       newStatus = "AVAILABLE";
       break;
     }
     String msg = String.format(getResources().getString(R.string.provider_disabled), provider, newStatus);
     Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
    
    avec
    <string name="provider_new_status">The provider %1$s has now a new status %2$s</string>
  • OnLocationChanged(Location location) : Cette méthode est appelée quand la localisation de l’utilisateur est mise à jour. L’argument représente la nouvelle position. Vous pouvez récupérer plusieurs informations comme la latitude, longitude, altitude et précision (en mètre). Ce qui donnera :
  • @Override
    public void onLocationChanged(Location location) {
     latitude = location.getLatitude();
     longitude = location.getLongitude();
     altitude = location.getAltitude();
     accuracy = location.getAccuracy();
    
     String msg = String.format(
       getResources().getString(R.string.new_location), latitude,
       longitude, altitude, accuracy);
     Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }
    
    avec
    <string name="new_location">New Location : Latitude = %1$s, Longitude = %2$s, Altitude = %3$s avec une précision de %4$s mètres </string>
Ce qui donne pour la classe complète :
package com.android.map;

import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

public class HelloGoogleMapActivity extends MapActivity implements
  LocationListener {

 private MapView mapView;
 private MapController mc;

 private LocationManager lm;

 private double latitude;
 private double longitude;
 private double altitude;
 private float accuracy;

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

  mapView = (MapView) this.findViewById(R.id.mapView);
  mapView.setBuiltInZoomControls(true);

  mc = mapView.getController();
  mc.setZoom(17);
 }

 @Override
 protected void onResume() {
  super.onResume();
  lm = (LocationManager) this.getSystemService(LOCATION_SERVICE);
  if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER))
   lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0,
     this);
  lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0,
    this);
 }

 @Override
 protected void onPause() {
  super.onPause();
  lm.removeUpdates(this);
 }

 @Override
 protected boolean isRouteDisplayed() {
  return false;
 }

 @Override
 public void onLocationChanged(Location location) {
  latitude = location.getLatitude();
  longitude = location.getLongitude();
  altitude = location.getAltitude();
  accuracy = location.getAccuracy();

  String msg = String.format(
    getResources().getString(R.string.new_location), latitude,
    longitude, altitude, accuracy);
  Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
 }

 @Override
 public void onProviderDisabled(String provider) {
  String msg = String.format(
    getResources().getString(R.string.provider_disabled), provider);
  Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
 }

 @Override
 public void onProviderEnabled(String provider) {
  String msg = String.format(
    getResources().getString(R.string.provider_enabled), provider);
  Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
 }

 @Override
 public void onStatusChanged(String provider, int status, Bundle extras) {
  String newStatus = "";
  switch (status) {
  case LocationProvider.OUT_OF_SERVICE:
   newStatus = "OUT_OF_SERVICE";
   break;
  case LocationProvider.TEMPORARILY_UNAVAILABLE:
   newStatus = "TEMPORARILY_UNAVAILABLE";
   break;
  case LocationProvider.AVAILABLE:
   newStatus = "AVAILABLE";
   break;
  }
  String msg = String.format(
    getResources().getString(R.string.provider_disabled), provider,
    newStatus);
  Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
 }

}
Petite explications :
  • Nous avons besoin d’une instance de la classe LocationManager. Cette dernière donne accès au service de localisation. Cela permet aux applications d’obtenir des mises à jour périodiques de la position de l’utilisateur.
  • On appele la méthode requestLocationUpdate pour la mise à jour via le Réseau (NetWork) et le GPS.
  • On implémente les méthodes obligatoires de LocationListener.
Sans oublier les permissions suivantes :
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  • INTERNET : Pour télécharger et afficher les cartes
  • ACCESS_FINE_LOCATION : Pour pouvoir localiser précisément l’utilisateur (GPS)
  • ACCESS_COARSE_LOCATION : Pour pouvoir localiser approximativement l’utilisateur (WIFI, 3G..)

Mise à jour de la position sur la carte

Maintenant que les nouvelles coordonnées de l’utilisateur sont récupérées, on aimerait mettre à jour la carte afin qu’elle se positionne à l’emplacement de l’utilisateur. Pour cela, il faut créer une instance de la classe GeoPoint (Représentant un point sur un carte) à l’aide des nouvelles coordonnées, puis demander à la carte de se déplacer à cette position. Ce qui donnera :
@Override
public void onLocationChanged(Location location) {
 latitude = location.getLatitude();
 longitude = location.getLongitude();
 altitude = location.getAltitude();
 accuracy = location.getAccuracy();

 String msg = String.format(
   getResources().getString(R.string.new_location), latitude,
   longitude, altitude, accuracy);
 Toast.makeText(this, msg, Toast.LENGTH_LONG).show();

 GeoPoint p = new GeoPoint((int) (latitude * 1E6), (int) (longitude * 1E6));
 mc.animateTo(p);
 mc.setCenter(p);
}
Voici le résultat de cet exemple :
Pour pouvoir mettre à jour les coordonnées de l’utilisateur à l’aide d’un émulateur, deux solutions sont disponibles :
  • l’émulateur contrôle : Fourni avec le SDK et intégré à Eclipse.
  • Un client telnet (PuttyTel) : Pour l’utiliser, il suffit de le lancer et remplir les champs suivants (Host Name : localhost et Port 5554) et pour finir taper help pour connaître les différentes commandes. En ce qui concerne la géolocalisation la commande est la suivante : geo fix latitude longitude.
Dans l’émulateur contrôle, dans la partie Location Controls, saisissez la nouvelle position de l’utilisateur (latitude, longitude) puis cliquez sur send.

Conclusion

Voila ce tutoriel est maintenant fini, en espérant qu’il vous a aidé à mieux comprendre la géolocalisation sousAndroid. N’hésitez pas à me contacter, commenter ou poser vos questions. Je vous fourni le code du projet ici.