Flutter iOS - cannot get current location for initialCameraPosition before loading Google Maps widget
The problem you are rendering your map before you have your initial position which I believe you realize this a FutureBuilder
would work but might be over kill. All you really need is a Boolean.
GoogleMapController mapController;
LocationData currentLocation;
Location location;
bool _serviceEnabled;
PermissionStatus _permissionGranted;
CameraPosition _center =
CameraPosition(target: SOURCE_LOCATION, zoom: CAMERA_ZOOM);
bool isLoading = false;
@override
void initState() {
super.initState();
location = new Location();
_getLocation();
}
_getLocation() async {
setState(() {
isLoading = true;
});
initialize();
currentLocation = await location.getLocation();
if (currentLocation == null) {
return;
}
_center = CameraPosition(
target: LatLng(currentLocation.latitude, currentLocation.longitude),
zoom: CAMERA_ZOOM);
setState(() {
isLoading = false;
});
print("CurrentLocation: $currentLocation");
}
Future<void> initialize() async {
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.DENIED) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.GRANTED) {
return;
}
}
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.orangeAccent,
title: Text('Map'),
centerTitle: true,
),
body: isLoading
? CircularProgressIndicator()
: Container(
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: _center,
myLocationEnabled: true,
),
),
);
}
Vuco
Updated on December 19, 2022Comments
-
Vuco over 1 year
I'm trying to implement a simple map functionality in my Flutter iOS aplication. I followed guides starting from Flutter location package readme, through Medium "Implement Real-time Location Updates on Google Maps in your Flutter Apps" article, ending on many stack questions regarding similar issues.
The problem is that I cannot get current location before loading the maps, therefore getting its LatLng in
initialCameraPosition
results in NPE. What I can do is loading the maps with hardcodedinitialCameraPosition
, current location loads correctly then and I can move camera to it either by dragging or by clicking the floating location button in the right-bottom corner.Here is my code sample:
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:location/location.dart'; const double CAMERA_ZOOM = 16; const LatLng SOURCE_LOCATION = LatLng(37.3317, -122.0325086); class MapPage extends StatefulWidget { @override _MapPageState createState() => _MapPageState(); } class _MapPageState extends State<MapPage> { GoogleMapController mapController; LocationData currentLocation; Location location; bool _serviceEnabled; PermissionStatus _permissionGranted; @override void initState() { super.initState(); location = new Location(); location.onLocationChanged.listen((event) { currentLocation = event; }); setInitialLocation(); } void setInitialLocation() async { _serviceEnabled = await location.serviceEnabled(); if (!_serviceEnabled) { _serviceEnabled = await location.requestService(); if (!_serviceEnabled) { return; } } _permissionGranted = await location.hasPermission(); if (_permissionGranted == PermissionStatus.denied) { _permissionGranted = await location.requestPermission(); if (_permissionGranted != PermissionStatus.granted) { return; } } currentLocation = await location.getLocation(); } void _onMapCreated(GoogleMapController controller) { mapController = controller; } CameraPosition initialCameraPosition() { LatLng target; if (currentLocation != null) target = LatLng(currentLocation.latitude, currentLocation.longitude); else target = SOURCE_LOCATION; return CameraPosition(target: target, zoom: CAMERA_ZOOM); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.orangeAccent, title: Text('Map'), centerTitle: true, ), body: GoogleMap( onMapCreated: _onMapCreated, initialCameraPosition: initialCameraPosition(), myLocationEnabled: true, ), ); } }
I understand that getting current location is an asynchronous process, so I also tried to use
FutureBuilder
in the body section:FutureBuilder<LocationData>( future: currentLocation, builder: (context, snapshot) { if (snapshot.hasData) { LocationData currentLocation = snapshot.data; return GoogleMap( onMapCreated: _onMapCreated, initialCameraPosition: CameraPosition( target: LatLng( currentLocation.latitude, currentLocation.longitude)), myLocationEnabled: true, ); } else if (snapshot.hasError) { return (Text("${snapshot.error}")); } return Center( child: CircularProgressIndicator( backgroundColor: Colors.orangeAccent, ), ); }, ),
which worked like a charm when I had to retrieve data from an http GET request, but this time it results only in an endless
CircularProgressIndicator
.I tried many other solutions from stack questions, including returning empty
Container
whencurrentLocation
is null, creating conditions forFutureBuilder snapshot.connectionState
, again with no success.Funny thing is that when I dug deeper into the
Location.getCurrentLocation()
method I found:/// Gets the current location of the user. /// /// Throws an error if the app has no permission to access location. /// Returns a [LocationData] object. Future<LocationData> getLocation() async { return LocationPlatform.instance.getLocation(); }
which then goes to:
/// Gets the current location of the user. /// /// Throws an error if the app has no permission to access location. /// Returns a [LocationData] object. Future<LocationData> getLocation() { throw UnimplementedError(); }
which puts me in doubt if this plugin even works at all.
Here is my
flutter doctor -v
result:[✓] Flutter (Channel master, v1.18.0-6.0.pre.82, on Mac OS X 10.15.4 19E287, locale pl-PL) • Flutter version 1.18.0-6.0.pre.82 at /Users/Vuco/flutter • Framework revision f35b673f2b (26 hours ago), 2020-04-19 02:45:01 +0530 • Engine revision a5e0b2f2f2 • Dart version 2.9.0 (build 2.9.0-1.0.dev 5b19445d9c) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3) • Android SDK at /Users/Vuco/Library/Android/sdk • Platform android-29, build-tools 29.0.3 • Java binary at: /Users/Vuco/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/192.6308749/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 11.4.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 11.4.1, Build version 11E503a • CocoaPods version 1.9.1 [✓] Android Studio (version 3.6) • Android Studio at /Users/Vuco/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/192.6308749/Android Studio.app/Contents • Flutter plugin version 45.0.1 • Dart plugin version 192.7761 • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211) [!] IntelliJ IDEA Ultimate Edition (version 2020.1) • IntelliJ at /Users/Vuco/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app ✗ Flutter plugin not installed; this adds Flutter specific functionality. ✗ Dart plugin not installed; this adds Dart specific functionality. • For information about installing plugins, see https://flutter.dev/intellij-setup/#installing-the-plugins [✓] VS Code (version 1.44.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.9.1 [✓] Connected device (1 available) • iPhone 8 • F60856B8-2C6E-401D-A0F9-06FFC7E09876 • ios • com.apple.CoreSimulator.SimRuntime.iOS-13-4 (simulator) ! Doctor found issues in 1 category.
and the dependencies I use:
google_maps_flutter: ^0.5.25+3 location: ^3.0.2
-
Vuco about 4 yearsGoing with what You suggested solved my issue, thanks a lot!
-
wcyankees424 about 4 yearsNo problem glad to help
-
Rageh Azzazy about 3 yearsgetLocation() function just stays forever and never returns i followed all steps above,, permissions are granted, and it just does not continue and does not return null what's going on here ?
-
Vuco about 3 years@RagehElAzzazy I haven't been working in Flutter for some time, but is there a chance you forgot to generate and add Google Maps API key to your project? Also version of google_maps_flutter I've been using back then required adding permission messages to Info.plist (for iOS), but that could change in current version as I don't see that instructions anywhere now. Have you followed Medium article that I linked in the post?
-
Alauddin Afif Cassandra almost 3 yearssame with @RagehElAzzazy. still not work on iOS.