Ara anem a mostrar la geolocalització. De moment, farem unes modificacions senzilles al programa que teníem per tal de gestionar els permisos d'ús del GPS i mostrar les coordenades obtingudes a la pantalla. Més endavant ja millorarem el programa, per deixar-lo més acabat.
Amb la biblioteca geolocator podem saber el lloc on es troba l'usuari. A més, disposem de l'opció de calcular la distància entre dues posicions. Per emprar aquesta biblioteca, cal anar al fitxer pubspec.yaml per dir-li que la volem fer servir. Ho hem de posar a dependencies, indicant quina és la versió que volem, que normalment ja ens surt de manera automàtica. Quan vam escriure aquest text era la 14.0.2.
dependencies:
flutter:
sdk: flutter
geolocator: ^14.0.2
Un cop afegit, cal picar al botó per baixar el paquet (
).
En el programa, cal importar el paquet shared_preferences.dart.
import 'package:shared_preferences/geolocator.dart';
A més, cal donar permís de geolocalització. Això ho farem anar al fitxer AndroidManifest.xml que es troba a la carpeta main de la carpeta src de la carpeta app de la carpeta android i afegir les línies del permís després de la de manifest i abans de la d'application:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<application
...
Atenció: Cal tenir en compte que l'absència d'aquest permís pot donar problemes a l'executar l'aplicació en el dispositiu, malgrat aquesta funcioni correctament en el simulador.
A la pantalla principal, necessitarem una funció per comprovar els permisos. Aquesta funció l'executarem a l'iniciar la pantalla principal. De moment, el resultat de la comprovació el guardarem a una variable, per mostrar-lo a la pantalla.
...
class _PantPrincipalState extends State<PantPrincipal> {
String _textPosicio = 'Posició desconeguda';
String _textPermis = 'Permisos no verificats.';
Future<String>? _rebut;
CridaWeb cridaWeb = CridaWeb();
@override
void initState() {
super.initState();
comprovaPermisos();
}
Future<void> comprovaPermisos() async {
LocationPermission permis = await Geolocator.checkPermission();
if (permis == LocationPermission.denied) {
setState(() {
_textPermis = 'Permís desactivat. Demanant permís...';
});
permis = await Geolocator.requestPermission();
}
setState(() {
if (permis == LocationPermission.whileInUse || permis == LocationPermission.always) {
_textPermis = 'Permís activat.';
} else {
_textPermis = 'Permís denegat permanentment.';
}
});
}
...
També tindrem una funció per llegir la posició.
...
Future<void> llegeixPosicio() async {
try {
final LocationSettings configPosicio = LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 100,
);
Position posicio = await Geolocator.getCurrentPosition(locationSettings: configPosicio);
setState(() {
_textPosicio = 'Latitud: ${posicio.latitude}, Longitud: ${posicio.longitude}';
});
} catch (e) {
setState(() {
_textPosicio = 'Error: $e';
});
}
}
...
El programa de la pantalla principal quedarà així:
pant_principal.dart
import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:telegram/data/crida_web.dart';
class PantPrincipal extends StatefulWidget {
const PantPrincipal({super.key});
@override
State<PantPrincipal> createState() => _PantPrincipalState();
}
class _PantPrincipalState extends State<PantPrincipal> {
String _textPosicio = 'Posició desconeguda';
String _textPermis = 'Permisos no verificats.';
Future<String>? _rebut;
CridaWeb cridaWeb = CridaWeb();
@override
void initState() {
super.initState();
comprovaPermisos();
}
Future<void> comprovaPermisos() async {
LocationPermission permis = await Geolocator.checkPermission();
if (permis == LocationPermission.denied) {
setState(() {
_textPermis = 'Permís desactivat. Demanant permís...';
});
permis = await Geolocator.requestPermission();
}
setState(() {
if (permis == LocationPermission.whileInUse || permis == LocationPermission.always) {
_textPermis = 'Permís activat.';
} else {
_textPermis = 'Permís denegat permanentment.';
}
});
}
Future<void> llegeixPosicio() async {
try {
final LocationSettings configPosicio = LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 100,
);
Position posicio = await Geolocator.getCurrentPosition(locationSettings: configPosicio);
setState(() {
_textPosicio = 'Latitud: ${posicio.latitude}, Longitud: ${posicio.longitude}';
});
} catch (e) {
setState(() {
_textPosicio = 'Error: $e';
});
}
}
@override
Widget build(BuildContext context) {
String txtEnv = "";
return Scaffold(
appBar: AppBar(title: Text("Enviar missatge"),),
body: Column(
children: [
Text(_textPermis),
SizedBox(height: 20),
Text(_textPosicio),
SizedBox(height: 20),
ElevatedButton(
onPressed: llegeixPosicio,
child: Text('GPS'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
maxLines: 2,
decoration: InputDecoration(
hintText: "Escriu el que vols enviar",
border: OutlineInputBorder(),
),
onChanged: (txt){
txtEnv = txt;
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextButton(
onPressed: () {
setState(() {
_rebut = cridaWeb.enviaDades(txtEnv);
});
},
child: Text("Envia text"),
),
),
FutureBuilder(future: _rebut, builder: (context, snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return CircularProgressIndicator();
} else if(snapshot.hasError){
return Text("Error: ${snapshot.error}");
} else if(snapshot.hasData){
return escriuResultats(snapshot.data);
} else {
return Text("");
}
})
],
),
);
}
}
Widget escriuResultats(String? dades){
if(dades != null){
return Text(dades.toString());
}
return Text("Alguna cosa ha fallat");
}

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.