Add location permissions and implement real-time location updates on the map

This commit is contained in:
Van Leemput Dayron
2025-10-05 23:35:56 +02:00
parent da39e0e164
commit 4a38ec720f
7 changed files with 156 additions and 13 deletions

View File

@@ -1,4 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<application <application
android:label="travel_mate" android:label="travel_mate"
android:name="${applicationName}" android:name="${applicationName}"

View File

@@ -11,6 +11,8 @@ PODS:
- GoogleMaps/Base (8.4.0) - GoogleMaps/Base (8.4.0)
- GoogleMaps/Maps (8.4.0): - GoogleMaps/Maps (8.4.0):
- GoogleMaps/Base - GoogleMaps/Base
- location (0.0.1):
- Flutter
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
@@ -21,6 +23,7 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`) - google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`)
- location (from `.symlinks/plugins/location/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
@@ -34,6 +37,8 @@ EXTERNAL SOURCES:
:path: Flutter :path: Flutter
google_maps_flutter_ios: google_maps_flutter_ios:
:path: ".symlinks/plugins/google_maps_flutter_ios/ios" :path: ".symlinks/plugins/google_maps_flutter_ios/ios"
location:
:path: ".symlinks/plugins/location/ios"
path_provider_foundation: path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin" :path: ".symlinks/plugins/path_provider_foundation/darwin"
shared_preferences_foundation: shared_preferences_foundation:
@@ -44,6 +49,7 @@ SPEC CHECKSUMS:
Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321 Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321
google_maps_flutter_ios: 0291eb2aa252298a769b04d075e4a9d747ff7264 google_maps_flutter_ios: 0291eb2aa252298a769b04d075e4a9d747ff7264
GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d
location: 155caecf9da4f280ab5fe4a55f94ceccfab838f8
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7

View File

@@ -45,5 +45,9 @@
<true/> <true/>
<key>UIApplicationSupportsIndirectInputEvents</key> <key>UIApplicationSupportsIndirectInputEvents</key>
<true/> <true/>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We need your location to show it on the map.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We need your location to show it on the map even in background.</string>
</dict> </dict>
</plist> </plist>

View File

@@ -1,5 +1,8 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
class MapContent extends StatefulWidget { class MapContent extends StatefulWidget {
const MapContent({super.key}); const MapContent({super.key});
@@ -9,7 +12,18 @@ class MapContent extends StatefulWidget {
} }
class _MapContentState extends State<MapContent> { class _MapContentState extends State<MapContent> {
static LatLng _pGooglePlex = LatLng(50.64864814740268, 3.7224066213297293); Location locationController = Location();
final Completer<GoogleMapController> _mapController =
Completer<GoogleMapController>();
LatLng? currentPosition;
@override
void initState() {
super.initState();
getLocationUpdate();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -21,7 +35,7 @@ class _MapContentState extends State<MapContent> {
children: [ children: [
TextField( TextField(
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Rechercher un lieu', hintText: 'Rechercher un lieu...',
prefixIcon: Icon(Icons.search), prefixIcon: Icon(Icons.search),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0), borderRadius: BorderRadius.circular(8.0),
@@ -29,17 +43,41 @@ class _MapContentState extends State<MapContent> {
), ),
), ),
SizedBox(height: 8.0), SizedBox(height: 8.0),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
onPressed: () {
// TODO : Logique de recherche à implémenter
},
child: Text('Chercher'),
),
),
SizedBox(height: 8.0),
Expanded( Expanded(
child: GoogleMap( child: currentPosition == null
? const Center(child: Text("Chargement..."))
: GoogleMap(
onMapCreated: (GoogleMapController controller) =>
_mapController.complete(controller),
initialCameraPosition: CameraPosition( initialCameraPosition: CameraPosition(
target: _pGooglePlex, target: currentPosition!,
zoom: 14.4746, zoom: 14.4746,
), ),
markers: { markers: {
Marker( Marker(
markerId: MarkerId('googlePlex'), markerId: MarkerId('currentLocation'),
position: _pGooglePlex, position: currentPosition!,
infoWindow: InfoWindow(title: 'Google Plex'), icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueAzure,
),
), ),
}, },
), ),
@@ -50,4 +88,46 @@ class _MapContentState extends State<MapContent> {
), ),
); );
} }
Future<void> _cameraToPosition(LatLng pos) async {
final GoogleMapController controller = await _mapController.future;
CameraPosition newCameraPosition = CameraPosition(target: pos, zoom: 13);
await controller.animateCamera(
CameraUpdate.newCameraPosition(newCameraPosition),
);
}
Future<void> getLocationUpdate() async {
bool serviceEnabled;
PermissionStatus permissionGranted;
serviceEnabled = await locationController.serviceEnabled();
if (serviceEnabled) {
serviceEnabled = await locationController.requestService();
} else {
return;
}
permissionGranted = await locationController.hasPermission();
if (permissionGranted == PermissionStatus.denied) {
permissionGranted = await locationController.requestPermission();
if (permissionGranted != PermissionStatus.granted) {
return;
}
}
locationController.onLocationChanged.listen((LocationData currentLocation) {
if (currentLocation.latitude != null &&
currentLocation.longitude != null) {
setState(() {
currentPosition = LatLng(
currentLocation.latitude!,
currentLocation.longitude!,
);
_cameraToPosition(currentPosition!);
print(currentPosition);
});
}
});
}
} }

View File

@@ -5,10 +5,12 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import location
import path_provider_foundation import path_provider_foundation
import shared_preferences_foundation import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
} }

View File

@@ -176,6 +176,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.15.6" version: "0.15.6"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
version: "4.1.2"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
@@ -208,6 +224,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.1.1" version: "5.1.1"
location:
dependency: "direct main"
description:
name: location
sha256: "06be54f682c9073cbfec3899eb9bc8ed90faa0e17735c9d9fa7fe426f5be1dd1"
url: "https://pub.dev"
source: hosted
version: "5.0.3"
location_platform_interface:
dependency: transitive
description:
name: location_platform_interface
sha256: "8aa1d34eeecc979d7c9fe372931d84f6d2ebbd52226a54fe1620de6fdc0753b1"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
location_web:
dependency: transitive
description:
name: location_web
sha256: ec484c66e8a4ff1ee5d044c203f4b6b71e3a0556a97b739a5bc9616de672412b
url: "https://pub.dev"
source: hosted
version: "4.2.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@@ -445,6 +485,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.6" version: "0.7.6"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
version: "1.4.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:

View File

@@ -34,6 +34,7 @@ dependencies:
shared_preferences: ^2.2.2 shared_preferences: ^2.2.2
path_provider: ^2.1.1 path_provider: ^2.1.1
bcrypt: ^1.1.3 bcrypt: ^1.1.3
location: ^5.0.0
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.