Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 36 di 37
  • livello intermedio
Indice lezioni

Geolocalizzazione

Lavorare con la geolocalizzazione dell’utente su un’app mobile, permette di migliorare l’esperienza utente sfruttando le informazioni sulla sua posizione.
Lavorare con la geolocalizzazione dell’utente su un’app mobile, permette di migliorare l’esperienza utente sfruttando le informazioni sulla sua posizione.
Link copiato negli appunti

Lavorare con la geolocalizzazione dell’utente è uno dei task più comuni all’interno di un’app mobile in quanto permette di migliorare l’esperienza utente fornendo informazioni basate sulla sua posizione.

In questa lezione vedremo come integrare questa funzionalità in un’app Flutter.

I plugin per la geolocalizzazione

Flutter, come tutti i framework per lo sviluppo mobile, offre questa possibilità attraverso diversi plugin forniti dalla propria community, ognuno dei quali offre una soluzione ottimizzata e semplice da utilizzare nelle proprie app.

Tra i plugin più utilizzati e apprezzati all’interno della community troviamo:

  • location, realizzata da uno sviluppatore indipendente;
  • geolocator, sviluppata da un’azienda.

Entrambe sono librerie valide e aggiornate frequentemente.

In questa lezione vedremo come utilizzare geolocator, lasciando al lettore come esercizio quello di modificare il codice di questa lezione per utilizzare la libreria location e di trarre le proprie decisioni in merito a quale sia più congeniale per le proprie attività.

Per utilizzare geolocator versione 3.0.0 o superiori è necessario il supporto alla versione AndroidX delle Android Support Librieries e quindi il progetto deve essere aggiornato per il supporto ad AndroidX. Ulteriori informazioni sono disponibili sulla documentazione ufficiale di Flutter.

Esempio pratico

Come sempre, creiamo un nuovo progetto come descritto nella lezione 6 e procediamo con una semplice applicazione che mostrerà un RaisedButton per recuperare:

  • la posizione corrente in coordinate spaziali (latitudine, longitudine);
  • l’indirizzo associato a quelle coordinate.

La struttura del nostro progetto sarà quindi la seguente

lib/
│── screens/
│   │── screen1
│   │      │── screen1.dart
│── theme/
│   │── style.dart
│── routes.dart

Diversamente dalle ultime lezioni, in questo esempio ci basterà lavorare all’interno di una singola schermata per estrapolare l’informazione di interesse. La definizione circa lo style e le routes è disponibile sul repository GitHub.

Installazione del plugin geolocator

Apriamo il file pubspec.yaml e inseriamo sotto la voce dependencies il nome del plugin di interesse come segue.

dependencies:
  # . . .
  geolocator: ^5.3.1

Eseguiamo dal nostro terminale il comando

flutter pub get

per installare il plugin.

Definizione dei permessi

Per permettere alla nostra applicazione di utilizzare la geolocalizzazione è necessario impostare i permessi per iOS e Android.

Per iOS è necessario aggiungere nel file Info.plist in ios/Runner le seguenti righe di configurazione:

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs access to location when open and in the background.</string>

di cui è possibile ovviamente modificare i messaggi definiti nel tag <string>. In particolare definendo le chiavi NSLocationAlwaysUsageDescription e NSLocationAlwaysAndWhenInUseUsageDescription abbiamo abilitato il supporto a versioni di iOS antecedenti alla 10 e la possibilità di recuperare la posizione anche quando l’applicazione non è in uso.

Per Android, apriamo il file AndroidManifest.xml in android/app/src/main e aggiungiamo all’interno del tag <manifest> quanto segue

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

Ulteriori dettagli sui permessi per la geolocalizzazione con Android sono disponibili nella nostra guida sullo sviluppo Android.

Definizione dell’UI

Apriamo adesso il file screen1.dart e definiamo il widget stateful Screen che si comporrà di due informazioni:

  • due Text che mostreranno le coordinate spaziali e l’indirizzo;
  • un RaisedButton per richiamare i metodi per l’estrazione dei dati.

Vediamo una semplice implementazione della nostra schermata.

class Screen1 extends StatefulWidget {
  @override
  _Screen1State createState() => _Screen1State();
}
class _Screen1State extends State<Screen1> {
  // . . .
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Lesson 36"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_currentAddress),
            Text(
                  "LAT: ${_currentPosition.latitude}, LNG: ${_currentPosition.longitude}"),
            RaisedButton(
              child: Text("Get location"),
              onPressed: () {
                // . . .
              },
            ),
          ],
        ),
      ),
    );
  }
}

Definizione dei metodi per il recupero della posizione e dell’indirizzo

Definiamo adesso i metodi e le variabili necessarie per l’estrapolazione delle informazioni riguardanti la posizione corrente dell’utente e l’indirizzo associato a quella posizione.

All’interno della classe _Screen1State aggiungiamo le seguenti tre variabili globali

Position _currentPosition;
  String _currentAddress;
  final Geolocator geolocator = Geolocator();

dove:

Variabile Descrizione
_currentPosition è di tipo Position e rappresenta una coordinata spaziale
_currentAddress è di tipo String e manterrà le informazioni circa l’indirizzo associato alla posizione corrente dell’utente
geolocator definisce un’istanza dell’oggetto Geolocator. Di default, l’oggetto Geolocator utilizzerà il FusedLocationProviderClient su Android quando sono disponibili i servizi di Google Play, altrimenti verrà utilizzato il LocationManager.
È possibile ignorare il comportamento forzando l’utilizzo del LocationManager come segue Geolocator()..forceAndroidLocationManager.

Definiamo adesso il metodo _getCurrentLocation che permetterà di:

  • estrapolare la posizione corrente dell’utente tramite il metodo getCurrentPosition specificando quale livello di accuratezza utilizzare;
  • impostare lo stato corrente per aggiornare l’informazione gestita dalla variabile _currentPosition;
  • effettuare il catch di possibili errori durante il recupero della posizione.

Di seguito una possibile implementazione.

void _getCurrentLocation() {
    geolocator
        .getCurrentPosition(desiredAccuracy: LocationAccuracy.best)
        .then((Position position) {
      setState(() {
        _currentPosition = position;
      });
    }).catchError((e) {
      print(e);
    });
  }

Aggiungiamo adesso il metodo per estrapolare l’indirizzo corrente dell’utente a partire dalla sua posizione. Definiamo il metodo async _getAddressFromLatLng che si occuperà di:

  • verificare se _currentPosition è diverso da null, e nel caso in cui lo fosse di restituire informazioni circa l’impossibilità di trovare un indirizzo;
  • invocare il metodo placemarkFromCoordinates di Geolocator per ottenere una lista di Placemark a partire dalle informazioni di _currentPosition;
  • impostare lo stato per _currentAddress;
  • gestire possibili errori durante l’estrazione dell’indirizzo.

Si riporta di seguito una possibile implementazione.

_getAddressFromLatLng() async {
    try {
      if (_currentPosition == null) {
        _currentAddress = 'No address found';
        return;
      }
      List<Placemark> p = await geolocator.placemarkFromCoordinates(
          _currentPosition.latitude, _currentPosition.longitude);
      Placemark place = p[0];
      setState(() {
        _currentAddress =
            "${place.locality}, ${place.postalCode}, ${place.country}";
      });
    } catch (e) {
      _currentAddress = 'No address found';
      return;
      print(e);
    }
  }

Per essere sicuri di invocarlo solo quando è disponibile la posizione dell’utente, modifichiamo il metodo _getCurrentLocation in modo da invocare nel corpo del metodo then il metodo _getAddressFromLatLng.

void _getCurrentLocation() {
    geolocator
        .getCurrentPosition(desiredAccuracy: LocationAccuracy.best)
        .then((Position position) {
      setState(() {
        _currentPosition = position;
      });
      _getAddressFromLatLng();
    }).catchError((e) {
      print(e);
    });
  }

Aggiornamento della UI

Definiti i metodi, non ci resta che modificare l’interfaccia come segue.

Aggiungiamo dei controlli sui widget Text in modo da mostrare il widget se e solo se le variabili _currentAddress e _currentPosition sono diverse da null. Ad esempio avremo:

if (_currentAddress != null) Text(_currentAddress),
    if (_currentPosition != null)
      Text(
          "LAT: ${_currentPosition.latitude}, LNG: ${_currentPosition.longitude}"),

Aggiorniamo infine la proprietà RaisedButton.onPressed come segue.

RaisedButton(
      child: Text("Get location"),
      onPressed: () {
        _getCurrentLocation();
      },
    )

Ora che è tutto pronto eseguiamo la nostra app per vedere i risultati delle modifiche fatte finora.

Figura 179. Esempio di utilizzo della libreria geolocator per a) Android e b) iOS (click per ingrandire)Esempio di utilizzo della libreria geolocator per a) Android e b) iOS

Come possiamo vedere, se l’utente clicca sul RaisedButton verrà invocato il metodo _getCurrentLocation() che popolerà le variabili _currentPosition e _currentAddress qualora venga individuata la posizione dell’utente, e mostrerà tali dati nei relativi widget Text.

Il codice di questa lezione è disponibile su GitHub.

Ti consigliamo anche