How do I display user location as soon as permission is granted?

421

I was receiving an target != null error and this was fixed with adding CircularProgressIndicator()

children: <Widget>[
      Container(
        decoration: BoxDecoration(
          // Login Box
          image: _buildBackgroundImage(),
        ),
      ),
      _userLocation == null
          ? CircularProgressIndicator()
          : GoogleMap(
              onMapCreated: _onMapCreated,
              initialCameraPosition: // required parameter that sets the starting camera position. Camera position describes which part of the world you want the map to point at.
                  CameraPosition(
                      target: _userLocation,
                      zoom: 14.5,
                      tilt: 0.0), //LatLng(53.467125, -2.233966)
              scrollGesturesEnabled: true,
              tiltGesturesEnabled: true,
              compassEnabled: true,
              rotateGesturesEnabled: true,
              myLocationEnabled: true,
              mapType: _currentMapType,
              zoomGesturesEnabled: true,
            ),
    ],
Share:
421
Andrew Stevenson
Author by

Andrew Stevenson

Updated on December 15, 2022

Comments

  • Andrew Stevenson
    Andrew Stevenson over 1 year

    I am creating a map application and I have an issue, where the app won't show the user location once permission is granted.

    Packages Used

    1. permission_handler
    2. google_maps_flutter.dart'

    I have got the location permission thing sorted, but the app doesn't show the user location as soon as the permissions have been granted. If I re-run the app, then it does.

    This is frustrating the hell out of me and I would appreciate it, if somebody could show me how to display the users' current location once the permissions have been granted?

    Here is the code

    import 'package:flutter/material.dart';
    import 'package:ManchesterMaps/models/locales.dart';
    import 'package:ManchesterMaps/widgets/drawers/map_drawer.dart';
    import 'package:ManchesterMaps/widgets/home_pages/my_places/list_places.dart';
    import 'package:ManchesterMaps/widgets/home_pages/settings/preferences.dart';
    import 'package:ManchesterMaps/widgets/home_pages/the_map/the_map.dart';
    import 'package:ManchesterMaps/widgets/home_pages/uni_security/uni_security_info.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter_localizations/flutter_localizations.dart';
    import 'package:circular_bottom_navigation/circular_bottom_navigation.dart';
    import 'package:circular_bottom_navigation/tab_item.dart';
    
    import './theme.dart' as Theme;
    
    void main() => runApp(App());
    
    class App extends StatefulWidget {
      @override
      _AppState createState() => _AppState();
    }
    
    class _AppState extends State<App> with WidgetsBindingObserver {
      PageController controller = PageController();
      int selected = 0;
    
    
    //BottomBar list
      List<TabItem> tabItems = List.of([
        new TabItem(Icons.home, "Campus Map", Theme.UniColors.primaryColour[500],
            labelStyle: TextStyle(
                color: Theme.UniColors.primaryColour[500],
                fontWeight: FontWeight.normal)),
        new TabItem(Icons.search, "Search", Theme.UniColors.primaryColour[500],
            labelStyle: TextStyle(
                color: Theme.UniColors.primaryColour[500],
                fontWeight: FontWeight.normal)),
        new TabItem(Icons.place, "My Places", Theme.UniColors.primaryColour[500],
            labelStyle: TextStyle(
                color: Theme.UniColors.primaryColour[500],
                fontWeight: FontWeight.normal)),
        new TabItem(
            Icons.security, "Security Info", Theme.UniColors.primaryColour[500],
            labelStyle: TextStyle(
                color: Theme.UniColors.primaryColour[500],
                fontWeight: FontWeight.normal)),
        new TabItem(Icons.settings, "Settings", Theme.UniColors.primaryColour[500],
            labelStyle: TextStyle(
                color: Theme.UniColors.primaryColour[300],
                fontWeight: FontWeight.normal)),
      ]);
    
      // Show Map Page
      CircularBottomNavigationController _navigationController =
          new CircularBottomNavigationController(0);
    
      @override
      Widget build(BuildContext context) {
        //Locale myLocale = Localizations.localeOf(context);
        return MaterialApp(
          localizationsDelegates: [
            // A class which loads the translations from JSON files
            const AppLocalizationsDelegate(),
            // Built-in localization of basic text for Material widgets
            GlobalMaterialLocalizations.delegate,
            // Built-in localization for text direction LTR/RTL
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          supportedLocales: [
            const Locale('en', ''),
            const Locale('fr', ''),
            const Locale('ar', ''),
            const Locale('de', ''),
            const Locale('es', ''),
            const Locale('hi', ''),
          ],
          onGenerateTitle: (BuildContext context) =>
              AppLocalizations.of(context).title,
          color: Theme.UniColors.primaryColour[300],
          theme: Theme.uniThemeData,
          home: Scaffold(
            body: Stack(
              children: <Widget>[
                PageView(
                  children: <Widget>[
                    Container(
                      child: TheMap(),
                    ),
                    Container(
                      child: Center(child: Text("Page 2")),
                    ),
                    Container(
                      child: ListPlaces(),
                    ),
                    Container(
                      child: UniSecurityInfo(),
                    ),
                    Container(
                      child: Preferences(),
                    ),
                  ],
                  controller: controller,
                  onPageChanged: (num) {
                    controller.animateToPage(
                      _navigationController.value,
                      curve: Curves.ease,
                      duration: Duration(milliseconds: 300),
                    );
                  },
                ),
              ],
            ),
            extendBody: true,
            bottomNavigationBar: CircularBottomNavigation(
              tabItems,
              controller: _navigationController,
              selectedCallback: (int selected) {
                _navigationController.value = selected;
    
                switch (selected) {
                  case 0:
                    {
                      controller.animateToPage(0,
                          curve: Curves.easeIn,
                          duration: Duration(milliseconds: 300));
                      break;
                    }
                  case 1:
                    {
                      controller.animateToPage(1,
                          curve: Curves.easeIn,
                          duration: Duration(milliseconds: 300));
                      break;
                    }
                  case 2:
                    {
                      controller.animateToPage(2,
                          curve: Curves.easeIn,
                          duration: Duration(milliseconds: 300));
                      break;
                    }
                  case 3:
                    {
                      controller.animateToPage(3,
                          curve: Curves.easeIn,
                          duration: Duration(milliseconds: 300));
                      break;
                    }
                  case 4:
                    {
                      controller.animateToPage(4,
                          curve: Curves.easeIn,
                          duration: Duration(milliseconds: 300));
                      break;
                    }
                }
              },
            ),
            drawer: MapDrawer(),
          ),
        );
      }
    }
    
    
    import 'dart:async';
    import 'package:flutter/material.dart';
    import 'package:permission_handler/permission_handler.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    import 'package:geolocator/geolocator.dart';
    
    class TheMap extends StatefulWidget {
      TheMap({Key key}) : super(key: key);
    
      _TheMapState createState() => _TheMapState();
    }
    
    class _TheMapState extends State<TheMap> with WidgetsBindingObserver {
      PermissionStatus _status;
      Completer<GoogleMapController> _mapController = Completer();
    
      LatLng _centre;
      Position currentLocation;
      MapType _currentMapType = MapType.normal;
    
      FutureOr<GoogleMapController> get controller => null;
    
    // check permissions
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
        // Check location permission has been granted
        PermissionHandler()
            .checkPermissionStatus(PermissionGroup
                .locationWhenInUse) //check permission returns a Future
            .then(_updateStatus); // handling in callback to prevent blocking UI
      }
    
      //double distanceInMeters = await Geolocator().distanceBetween(52.2165157, 6.9437819, 52.3546274, 4.8285838);
    
      // method that is called on map creation and takes a MapController as a parameter
      void _onMapCreated(GoogleMapController controller) {
        PermissionHandler()
            .checkPermissionStatus(PermissionGroup
                .locationWhenInUse) //check permission returns a Future
            .then(_updateStatus); // handling in callback to prevent blocking UI
    
          _mapController.complete(
              controller); // manages camera function (position, animation, zoom).
        }
    
    
      Future<Position> locateUser() async {
        return Geolocator()
            .getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
      }
    
      //TODO: Get Users' location
      getUserLocation() async {
        currentLocation = await locateUser();
        setState(() {
          _centre = LatLng(currentLocation.latitude ?? 53.467125,
              currentLocation.longitude ?? -2.233966);
        });
        print('centre $_centre');
      }
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget>[
            GoogleMap(
              onMapCreated: _onMapCreated,
              initialCameraPosition: // required parameter that sets the starting camera position. Camera position describes which part of the world you want the map to point at.
                  CameraPosition(
                      target: LatLng(53.467125, -2.233966), zoom: 14.5, tilt: 0.0),
              scrollGesturesEnabled: true,
              tiltGesturesEnabled: true,
              compassEnabled: true,
              rotateGesturesEnabled: true,
              myLocationEnabled: true,
              mapType: _currentMapType,
              zoomGesturesEnabled: true,
            ),
          ],
        );
      }
    
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    
      // check permissions when app is resumed
      // this is when permissions are changed in app settings outside of app
      void didChangeAppLifecycleState(AppLifecycleState state) {
        if (state == AppLifecycleState.resumed) {
          PermissionHandler()
              .checkPermissionStatus(PermissionGroup.locationWhenInUse)
              .then(_updateStatus);
        }
        print("STATE -> $state");
      }
    
      /*void _askPermission() {
        PermissionHandler().requestPermissions(
            [PermissionGroup.locationWhenInUse]).then(_onStatusRequested);
      }*/
    
      void _onStatusRequested(Map<PermissionGroup, PermissionStatus> statuses) {
        final status = statuses[PermissionGroup.locationWhenInUse];
        if (status != PermissionStatus.granted) {
          // On iOS if "deny" is pressed, open App Settings
          PermissionHandler().openAppSettings();
        } else {
          //_updateStatus(status);
          print("STATUS -> $status");
        }
      }
    
      void _updateStatus(PermissionStatus status) {
        if (status != _status) {
          // check status has changed
          setState(() {
            _status = status; // update
            _onMapCreated(controller);
          });
        } else {
          if (status != PermissionStatus.granted) {
            print("REQUESTING PERMISSION");
            PermissionHandler().requestPermissions(
                [PermissionGroup.locationWhenInUse]).then(_onStatusRequested);
          } 
        }
      }
    }
    

    Am I missing something really obvious here?

    Any help is extremely appreciated.

    thanks