L’objectif est de géolocaliser l’équipement avec assez de précision en utilisant les services de géolocalisation d’Android qui fournit une position géographique selon une latitude et une longitude.
Le fournisseur de localisation (location provide) propose deux types de géolocalisation :
Le système Android donne un accès de localisation aux applications à condition que les paramètres de sécurité les y autorisent : Paramètres de configuration -> Accès aux données de localisation.
Les outils de localisation dans le package android.location.
L’application a besoin des droits d’accès (uses-permission
) pour utiliser les fonctionnalités de localisation :
ACCESS_FINE_LOCATION
;ACCESS_COARSE_LOCATION
;Pour cela, il faut modifier le fichier AndroidManifest.xml
de l’application :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tv.myapplication5">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
...
</manifest>
Il faut tout d’abord disposer d’un gestionnaire de position à partir de la classe LocationManager.
On le récupère de la manière suivante :
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Il existe plusieurs méthodes pour récupérer les fournisseurs de position disponibles sur le terminal mobile :
getAllProviders()
qui permet de récupérer une liste de tous les noms de fournisseur (même si vous n’avez pas les droits d’accès pour certains) ;
getProviders(boolean enabledOnly)
qui permet de récupérer une liste de tous les noms de fournisseur accessible ;
getProvider(String name)
qui retourne un LocationProvider
à partir de son nom.
Il est aussi possible d’obtenir le fournisseur à partir de critères à déterminer avec la classe Criteria
. On utilisera alors la méthode getBestProvider(Criteria criteria, boolean enabledOnly)
afin d’obtenir le nom du fournisseur qui se rapproche le plus des critères demandés ou getProviders(Criteria criteria, boolean enabledOnly)
qui retourne une liste de noms.
Pour obtenir la dernère localisation connue, on appellera la méthode getLastKnownLocation()
qui retourne un objet de type Location
dont on pourra extraire la latitude avec double getLatitude()
et la longitude avec double getLongitude()
.
La classe Location est ene classe de données représentant un emplacement géographique. L’emplacement peut comprendre une latitude, une longitude, un horodatage et d’autres informations telles que l’altitude, la vitesse, …
Exemple :
...
LocationManager locationManager = null;
private String fournisseur;
private void initialiserLocalisation()
{
if(locationManager == null)
{
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Criteria criteres = new Criteria();
// la précision : (ACCURACY_FINE pour une haute précision ou ACCURACY_COARSE pour une moins bonne précision)
criteres.setAccuracy(Criteria.ACCURACY_FINE);
// l'altitude
criteres.setAltitudeRequired(true);
// la direction
criteres.setBearingRequired(true);
// la vitesse
criteres.setSpeedRequired(true);
// la consommation d'énergie demandée
criteres.setCostAllowed(true);
criteres.setPowerRequirement(Criteria.POWER_HIGH);
fournisseur = locationManager.getBestProvider(criteres, true);
Log.d("GPS", "fournisseur : " + fournisseur);
}
if(fournisseur != null)
{
// dernière position connue
Location localisation = locationManager.getLastKnownLocation(fournisseur);
Log.d("GPS", "localisation : " + localisation.toString());
String coordonnees = String.format("Latitude : %f - Longitude : %f\n", localisation.getLatitude(), localisation.getLongitude());
Log.d("GPS", "coordonnees : " + coordonnees);
String autres = String.format("Vitesse : %f - Altitude : %f - Cap : %f\n", localisation.getSpeed(), localisation.getAltitude(), localisation.getBearing());
Log.d("GPS", autres);
//String timestamp = String.format("Timestamp : %d\n", localisation.getTime());
//Log.d("GPS", "timestamp : " + timestamp);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = new Date(localisation.getTime());
Log.d("GPS", sdf.format(date));
}
}
...
Il est possible de créer une classe “écouteur” pour ce service en implémentant l’interface LocationListener qui reçoit les mises à jour de localisation par la méthode onLocationChanged(Location location)
.
La méthode onStatusChanged()
est appelée lorsqu’il y aura un changement d’état sur le fournisseur de localisation. Les méthodes onProviderEnabled(String provider)
et onProviderDisabled(String provider)
seront appelées quand le fournisseur de localisation est activé ou désactivé.
Exemple :
import android.location.*;
class MyLocationListener implements LocationListener
{
public void onLocationChanged(Location localisation)
{
Log.d("GPS", "localisation : " + localisation.toString());
String coordonnees = String.format("Latitude : %f - Longitude : %f\n", localisation.getLatitude(), localisation.getLongitude());
Log.d("GPS", "coordonnees : " + coordonnees);
}
@Override
public void onStatusChanged(String fournisseur, int status, Bundle extras)
{
Toast.makeText(, fournisseur + " état : " + status, Toast.LENGTH_SHORT).show();
}
@Override
public void onProviderEnabled(String fournisseur)
{
Toast.makeText(, fournisseur + " activé !", Toast.LENGTH_SHORT).show();
}
@Override
public void onProviderDisabled(String fournisseur)
{
Toast.makeText(, fournisseur + " désactivé !", Toast.LENGTH_SHORT).show();
}
}
On a vu que pour obtenir la dernière position connue du terminal mobile, il fallait appeler getLastKnownLocation(String provider)
.
Mais la dernière position connue n’est pas forcément la position actuelle ! Il faudra configurer la mise à jour automatique de la position en fonction de critères de temps et/ou de distance.
On pourra pour cela utiliser la méthode requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
avec :
provider
le fournisseur de position ;minTime
la période entre deux mises à jour en millisecondes (attention à la batterie) ;minDistance
la période entre deux mises à jour en mètres ;listener
est l’écouteur qui sera lancé dès que le fournisseur sera activé.Remarque : attention à vos choix de minTime
et de minDistance
car ils vont influer sur la consommation d’énergie.
Exemple :
...
LocationManager locationManager = null;
private String fournisseur;
MyLocationListener myLocationListener; // écouteur
private void initialiserLocalisation()
{
...
if(fournisseur != null)
{
// dernière position connue
Location localisation = locationManager.getLastKnownLocation(fournisseur);
myLocationListener = new MyLocationListener();
if(localisation != null)
{
// on notifie la localisation
myLocationListener.onLocationChanged(localisation);
}
// on configure la mise à jour automatique : au moins 10 mètres et 15 secondes
locationManager.requestLocationUpdates(fournisseur, 15000, 10, myLocationListener);
}
}
Lorsque le service est suspendu, il est indispensable de supprimer toutes les mises à jour de localisation avec la méthode removeUpdates()
:
private void arreterLocalisation()
{
if(locationManager != null)
{
locationManager.removeUpdates(myLocationListener);
myLocationListener = null;
}
}
La classe Geocoder permet de gérer le géocodage et le géocodage inverse. Le géocodage est le processus de transformation d’une adresse postale (ou d’une autre description) d’un lieu en coordonnées (latitude, longitude) et le géocodage inverse est le processus de transformation d’une coordonnée (latitude, longitude) en une adresse (partielle). Les détails dans une description d’emplacement géocodée inversée peut varier.
Exemple :
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> adresses = null;
try
{
adresses = geocoder.getFromLocation(localisation.getLatitude(), localisation.getLongitude(), 1);
}
catch (IOException ioException)
{
Log.e("GPS", "erreur", ioException);
}
catch (IllegalArgumentException illegalArgumentException)
{
Log.e("GPS", "erreur " + coordonnees, illegalArgumentException);
}
if (adresses == null || adresses.size() == 0)
{
Log.e("GPS", "erreur aucune adresse !");
}
else
{
Address adresse = adresses.get(0);
ArrayList<String> addressFragments = new ArrayList<String>();
for(int i = 0; i <= adresse.getMaxAddressLineIndex(); i++)
{
addressFragments.add(adresse.getAddressLine(i));
}
Log.d("GPS", TextUtils.join(System.getProperty("line.separator"), addressFragments));
}
package com.example.tv.myapplicationgps;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.Criteria;
import android.location.LocationProvider;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class MyActivity extends AppCompatActivity
{
LocationManager locationManager = null;
private String fournisseur;
private TextView latitude;
private TextView longitude;
private TextView Adresse;
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
LocationListener ecouteurGPS = new LocationListener() {
@Override
public void onLocationChanged(Location localisation)
{
Toast.makeText(getApplicationContext(), fournisseur + " localisation", Toast.LENGTH_SHORT).show();
Log.d("GPS", "localisation : " + localisation.toString());
String coordonnees = String.format("Latitude : %f - Longitude : %f\n", localisation.getLatitude(), localisation.getLongitude());
Log.d("GPS", coordonnees);
String autres = String.format("Vitesse : %f - Altitude : %f - Cap : %f\n", localisation.getSpeed(), localisation.getAltitude(), localisation.getBearing());
Log.d("GPS", autres);
//String timestamp = String.format("Timestamp : %d\n", localisation.getTime());
//Log.d("GPS", "timestamp : " + timestamp);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = new Date(localisation.getTime());
Log.d("GPS", sdf.format(date));
String strLatitude = String.format("Latitude : %f", localisation.getLatitude());
String strLongitude = String.format("Longitude : %f", localisation.getLongitude());
latitude.setText(strLatitude);
longitude.setText(strLongitude);
List<Address> adresses = null;
try
{
adresses = geocoder.getFromLocation(localisation.getLatitude(), localisation.getLongitude(), 1);
}
catch (IOException ioException)
{
Log.e("GPS", "erreur", ioException);
} catch (IllegalArgumentException illegalArgumentException)
{
Log.e("GPS", "erreur " + coordonnees, illegalArgumentException);
}
if (adresses == null || adresses.size() == 0)
{
Log.e("GPS", "erreur aucune adresse !");
} else {
Address adresse = adresses.get(0);
ArrayList<String> addressFragments = new ArrayList<String>();
String strAdresse = adresse.getAddressLine(0) + ", " + adresse.getLocality();
Log.d("GPS", "adresse : " + strAdresse);
for(int i = 0; i <= adresse.getMaxAddressLineIndex(); i++)
{
addressFragments.add(adresse.getAddressLine(i));
}
Log.d("GPS", TextUtils.join(System.getProperty("line.separator"), addressFragments));
Adresse.setText(TextUtils.join(System.getProperty("line.separator"), addressFragments));
}
}
@Override
public void onProviderDisabled(String fournisseur)
{
Toast.makeText(getApplicationContext(), fournisseur + " désactivé !", Toast.LENGTH_SHORT).show();
}
@Override
public void onProviderEnabled(String fournisseur)
{
Toast.makeText(getApplicationContext(), fournisseur + " activé !", Toast.LENGTH_SHORT).show();
}
@Override
public void onStatusChanged(String fournisseur, int status, Bundle extras)
{
switch(status)
{
case LocationProvider.AVAILABLE:
Toast.makeText(getApplicationContext(), fournisseur + " état disponible", Toast.LENGTH_SHORT).show();
break;
case LocationProvider.OUT_OF_SERVICE:
Toast.makeText(getApplicationContext(), fournisseur + " état indisponible", Toast.LENGTH_SHORT).show();
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
Toast.makeText(getApplicationContext(), fournisseur + " état temporairement indisponible", Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(getApplicationContext(), fournisseur + " état : " + status, Toast.LENGTH_SHORT).show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.commande);
latitude = (TextView) findViewById(R.id.textViewLatitude);
longitude = (TextView) findViewById(R.id.textViewLongitude);
Adresse = (TextView) findViewById(R.id.textViewAdresse);
Log.d("GPS", "onCreate");
initialiserLocalisation();
}
@Override
protected void onDestroy()
{
super.onDestroy();
arreterLocalisation();
}
private void initialiserLocalisation()
{
if (locationManager == null)
{
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
Criteria criteres = new Criteria();
// la précision : (ACCURACY_FINE pour une haute précision ou ACCURACY_COARSE pour une moins bonne précision)
criteres.setAccuracy(Criteria.ACCURACY_FINE);
// l'altitude
criteres.setAltitudeRequired(true);
// la direction
criteres.setBearingRequired(true);
// la vitesse
criteres.setSpeedRequired(true);
// la consommation d'énergie demandée
criteres.setCostAllowed(true);
//criteres.setPowerRequirement(Criteria.POWER_HIGH);
criteres.setPowerRequirement(Criteria.POWER_MEDIUM);
fournisseur = locationManager.getBestProvider(criteres, true);
Log.d("GPS", "fournisseur : " + fournisseur);
}
if (fournisseur != null)
{
// dernière position connue
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
Log.d("GPS", "no permissions !");
return;
}
Location localisation = locationManager.getLastKnownLocation(fournisseur);
if(localisation != null)
{
// on notifie la localisation
ecouteurGPS.onLocationChanged(localisation);
}
// on configure la mise à jour automatique : au moins 10 mètres et 15 secondes
locationManager.requestLocationUpdates(fournisseur, 15000, 10, ecouteurGPS);
}
}
private void arreterLocalisation()
{
if(locationManager != null)
{
locationManager.removeUpdates(ecouteurGPS);
ecouteurGPS = null;
}
}
}