Loupe

Utiliser la géolocation dans vos applications Flutter

De nos jours, de nombreuses applications demandent l'accès à la géolocation de l'utilisateur. Nous allons voir aujourd'hui comment l'utiliser dans nos applications Flutter.

Ready ? Steady? Gooooooooooooooooooooooooooooooo !

Ne partez pas si vite ! C'est peut-être simple pas si compliqué à mettre en place mais il y a quand même quelques petites choses à écrire avant de pouvoir utiliser la géolocalisation :)

Installation du package Location

Dans votre projet, ouvrez le fichier pubspec.yaml et ajoutez en dessous de dependencies la référence au package location :

dependencies: 
    location: ^2.3.5

Ajourd'hui, la version la plus récente est la 2.3.5, j'ai donc choisi celle-ci. Vous pouvez vérifier la dernière version sur la page du plugin ici. Le caret, ou accent circonflexe (oui oui, c'est comme ça que s'appelle le "chapeau chinois"), permet d'indiquer que l'on accepte d'utiliser la version mineure la plus récente de la version majeure utilisée. Autrement dit, quand la version 2.4.0 sortira, mon application utilisera cette version, mais pas la version 3.0.0 quand elle sortira.

Installons ensuite le package avec la commande

flutter pub get

Ajout des permissions

Android

Il faut ensuite indiquer à Android et iOS que votre application utilisera la géolocalisation. Pour cela, ajoutez la ligne suivante à votre manifest android (android/app/src/main/AndroidManifest.xml) à l'intérieur de la balise <manifest> :

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Puis ajoutez les dépendances suivantes dans le fichier android/build.gradle (différent de celui d'avant) :

dependencies { 
     classpath 'com.android.tools.build:gradle:3.3.0' 
     classpath 'com.google.gms:google-services:4.2.0' 
}

Depuis la version 2.0 du package location, le package utilise AndroidX (en gros, c'est une nouvelle façon de gérer les packages - voir la documentation officielle pour plus d'informations). Cela implique donc des modifications à apporter dans les fichiers Android. Parmi celles-ci, il faut ajouter les lignes suivantes au fichier gradle.properties pour indiquer qu'on utilise AndroidX :

android.enableJetifier=true 
android.useAndroidX=true 
org.gradle.jvmargs=-Xmx1536M

Puis vérifiez que vous avez bien la valeur suivante dans le fichier android/app/build.gradle :

compileSdkVersion 28

iOS

De même pour iOS, il faut indiquer que nous allons utiliser la géolocalisation. Pour iOS, cela se fait au travers des propriétés NSLocationWhenInUseUsageDescription et NSLocationAlwaysUsageDescription dans le fichier Info.plist :

<key>NSLocationAlwaysUsageDescription</key>
<string>Indiquer ici votre raison d'utiliser la géolocalisation lorsque l'application est au premier plan</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Indiquer ici votre raison d'utiliser la géolocalisation n'importe quand</string>

Récupération de la géolocalisation

Comment ça fonctionne ?

Là, la réponse est simple. Pour récupérer la géolocalisation du téléphone, il suffit d'utiliser la méthode getLocation() :

var location = new Location();
var currentLocation = await location.getLocation();

La méthode getLocation est une Future retournant un objet de type LocationDate, il est donc nécessaire d'attendre son retour à l'aide du mot clé await.

Comment l'utiliser sur une page ?

Là, la réponse se complique... Effectivement, la récupération de la géolocalisation étant une action asynchrone, il est nécessaire d'attendre que l'action se fasse avant pour pouvoir utiliser nos données. En Flutter, cela se fait au travers du widget FutureBuilder.

FutureBuilder<TResult> FutureBuilder({Key key}, {Future<TResult> future}, {TResult initialData}, {Widget Function(BuildContext, AsyncSnapshot<LocationData>) builder})

Pour utiliser le FutureBuilder, nous allons constuire notre Future. Un peu plus tôt, je vous ai expliqué qu'on récupérait la géolocalisation avec la méthode location.getLocation(). Cette méthode retourne un objet de type LocationData. Nous allons donc stocker notre résultat dans une variable currentLocation, de la manière suivante :

Future<LocationData> currentLocation;
Location location;

@override
void initState() {
    super.initState();

    location = new Location();
    currentLocation = location.getLocation();
}
 

Nous pouvons maintenant créer notre interface en utilisant le FutureBuilder de la sorte :

@override
Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
        title: Text(widget.title),
        ),
        body: FutureBuilder(
            future: currentLocation,
            builder: (BuildContext context, AsyncSnapshot<LocationData> snapshot) {
            switch (snapshot.connectionState) {
                case ConnectionState.waiting:
                    return new Center(child: new CircularProgressIndicator());
                case ConnectionState.done:
                    if (snapshot.hasError) {
                        return new Text(
                        '${snapshot.error}',
                        style: TextStyle(color: Colors.red),
                        );
                    } else {
                        return new Center(
                        child: Text(snapshot.data.latitude.toString() +
                            " - " +
                            snapshot.data.longitude.toString()),
                        );
                    }
                default:
                    return new Text('');
            }
            })
    );
}
 

Maintenant, si comme moi vous souhaitez pouvoir rafraîchir la localisation, vous pouvez ajouter un bouton pour rafraîchir les données. Pour ma part, j'ai choisi d'utiliser le FloatingActionButton.

floatingActionButton: FloatingActionButton(
    onPressed: () {
        setState(() {
            currentLocation = location.getLocation();
        });
    },
    tooltip: 'Refresh',
    child: Icon(Icons.refresh),
),
 

L'appui sur ce bouton déclenche l'action et rafraîchit la valeur de currentLocation. Si vous vous souvenez bien, le setState permet d'indiquer qu'il faudra rafraîchir l'interface avec cette nouvelle valeur.

Et voila, vous pouvez maintenant utiliser la géolocalisation dans vos application Flutter. Il existe aussi une méthode permettant de récupérer la localisation en temps réel avec les mises à jour en utilisant la méthode location.onLocationChanged().listen. Je ne la décrirai pas dans cet article, j'ai confiance en vous, vous vous en sortirez sans moi.

Pour ceux qui voudraient en lire un peu plus sur Flutter, voici quelques liens :

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus