Search code examples
iospermissionsflutterlocation

Granting location permission with Flutter at iOS


The below code run smoothly at Android, but stuck at iOS, when I click the map icon, the system should update my location:

import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:flutter/services.dart';
import 'package:simple_permissions/simple_permissions.dart';

class LocationState extends State {

  String _loca_ext;

  Location _location = new Location();
  Map<String, double> _currentLocation;

  String error;

  @override
  void initState() {
    super.initState();

    setState(() {
      _loca_ext = 'Clik to update location';
    });

  }

  // Platform messages are asynchronous, so we initialize in an async method.
  _getLocation() async {
    Map<String, double> location;
    // Platform messages may fail, so we use a try/catch PlatformException.
    try {
      await SimplePermissions.requestPermission(Permission.AccessFineLocation);
      location = await _location.getLocation();
      error = null;
    } on PlatformException catch (e) {
      if (e.code == 'PERMISSION_DENIED') {
        error = 'Permission denied';
      } else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {
        error =
        'Permission denied - please ask the user to enable it from the app settings';
      }
      location = null;
    }
    print("error $error");

    setState(() {
      _currentLocation = location;
      _loca_ext = ('${_currentLocation["latitude"]}, ${_currentLocation["longitude"]}' ?? 'Grant location Access');
      print(_currentLocation);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Baby Name Votes')),
      body: _buildBody(context),
    );
  }

  Widget _buildBody(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey),
          borderRadius: BorderRadius.circular(5.0),
        ),
        child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              ButtonTheme.bar(
                  child: ButtonBar(
                      children: <Widget>[
                        Text.rich(
                          TextSpan(text: '$_loca_ext'),
                        ),
                        FlatButton(
                          child: const Icon(Icons.map),
                          onPressed: () {
                            _getLocation();
                            var alt = _currentLocation["latitude"];
                            print("my $alt at location is: $_currentLocation");
                          },
                        )
                      ])
              )
            ]),
      ),
    );
  }
}

With iOS, it gave the below error:

error Permission denied

Knowing that in the Info.plist, I added the below:

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location in the background.</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>

NOTE

It work if I granted it manually in the settings/privacy/location, but I need to do it programmatically, or guide the user to do it.


Solution

  • Have you tried using https://pub.dev/packages/permission?

    Sample methods:

    import 'package:permission/permission.dart';
    
    var permissions = await Permission.getPermissionsStatus([PermissionName.Calendar, PermissionName.Camera]);
    
    var permissionNames = await Permission.requestPermissions([PermissionName.Calendar, PermissionName.Camera]);
    
    Permission.openSettings;
    

    But like the comments say, if the permission is rejected, then you have to manually go to the settings to enable it. For more understanding, see medium/Requesting Location Permissions in iOS (March 2018)

    Users have only one chance to respond to these alerts, so you want to make your request at the right time and provide a good reason for it. If the user doesn’t allow access, they’ll need to go to the settings to enable location access.