Flutter: wait user enable GPS permission & location
Tags: flutter, gps, dart, location
Published: 2020-03-28 21:52:11

Getting user’s current location is the most important task in apps those provides services like food ordering, transportation, health tracking, social networking or lot more. This location information mainly based on getting user’s latitude & longitude. Using latitude & longitude values, you can easily determine the exact location of a user.

#What is Latitude and Longitude ?
Latitude and longitude are angles that uniquely define points on a sphere. Together, the angles comprise a coordinate scheme that can locate or identify geographic positions on the surfaces of planets such as the earth.
#What is Flutter?
Flutter is a free and open-source mobile UI framework created by Google and released in May 2017.
It’s a cross-platform tool intended for creating Android and iOS apps from a single code base by using a modern, reactive framework.
To develop with Flutter, you will use a programming language called Dart. The language was created also by Google in October 2011, but it has improved a lot over these past years.

#New Flutter project
Let’s start by creating a new flutter project, just copy&paste the following commnad lines in the terminal.
```
#New Flutter project
$ flutter create gpsproject

#Open the project with VisualStudio code
$ cd gpsproject && code .
```
In the website [pub.dev](https://pub.dev) you can search and find useful packages to build [Dart](https://dart.dev)and [flutter](https://flutter.dev) apps.
There is two plugins for GPS location that we can use it with Flutter, let’s get started by exploring them.

##Flutter Location Plugin
This [plugin](https://pub.dev/packages/location#flutter-location-plugin) for Flutter handles getting location on Android and iOS. It also provides callbacks when location is changed. Even it provides settings for optimizing performance or battery.
1.Add this to file `pubspec.yaml`file:
```
dependencies:
  location: ^3.0.1
```
Wait for flutter pub get finish downloading dependencies
`flutter pub get`
2.Add a permission to Android Manifest:
```
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
```
3.Add permissions to iOS `Info.plist`
```
<key>NSLocationAlwaysUsageDescription</key>
<string>Needed to access location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Needed to access location</string>
```
4.Now in your Dart code, you can use:
``` import 'package:location/location.dart'; ```

##Flutter Geolocator Plugin
This [plugin](https://pub.dev/packages/geolocator) provides a cross-platform (iOS, Android) API for generic location (GPS etc.) functions, it has some features as shown bellow:
* Get the last known location;
* Get continuous location updates;
* Check if location services are enabled on the device;
* Translate an address to geocoordinates and vice verse (a.k.a. Geocoding);
* Calculate the distance (in meters) between two geocoordinates;
* Check the availability of Google Play services (on Android only).

1.Add this to file `pubspec.yaml` file:
```
dependencies:
  geolocator: ^5.3.0
```
Wait for flutter pub get finish downloading dependencies
`flutter pub get`
2.Add a permission to Android Manifest:
```
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
```
3.Add permissions to iOS `Info.plist`
```
<key>NSLocationAlwaysUsageDescription</key>
<string>Needed to access location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Needed to access location</string>
```
Add the following to your `gradle.properties` file:
```
android.useAndroidX=true
android.enableJetifier=true
```
4.Make sure you set the `compileSdkVersion` in your `android/app/build.gradle` file to 28:
```
android {
 compileSdkVersion 28
 ...
}
```
5.Now in your Dart code, you can use:
```
import 'package:geolocator/geolocator.dart';
```

##Flutter Permission handler Plugin
This [plugin](https://pub.dev/packages/permission_handler) provides a cross-platform (iOS, Android) API to request and check permissions. Below you can find some features about this plugin:
* Check if a permission is granted.
* Request permission for a specific feature.
* Open app settings so the user can enable a permission.
We will use this plugin to check the permission status of location service.

1.Add this to file `pubspec.yaml` file:
```
dependencies:
  permission_handler: ^4.4.0+hotfix.2
```
2.Now in your Dart code, you can use:
`import 'package:permission_handler/permission_handler.dart';`
The possible permission statuses are:
**Granted**: Your app has been given permission to use the feature in question.
**Denied**: Your app has been given permission to use the feature in question.
**Disabled**: Feature in question is disabled i.e. when the Location feature is disabled.
**Restricted**: (iOS only)OS has restricted access to a specific feature due to something like parental controls.
Unknown: Unknown state of permissions.

##Android Intent Plugin
This plugin allows Flutter apps to launch arbitrary intents when the platform is Android. Not supported on iOS.
We will use this plugin to open settings -> location menu.

1.Add this to file pubspec.yaml file:
```
dependencies:
  android_intent: ^0.3.6+12.
```
2.Now in your Dart code, you can use:
`import 'package:android_intent/android_intent.dart'; `

#Show me code!
First, I would like to give the difference for some variables:
`ACCESS_FINE_LOCATION` is the most precise location coordinates.
`ACCESS_COARSE_LOCATION` gives results equal to about a city block.
`NSLocationWhenInUseUsageDescription` needs access to location when open app.
`NSLocationAlwaysUsageDescriptionneeds` access to location when the app run in the background.
`NSLocationAlwaysAndWhenInUseUsageDescriptionneeds` access to location when the app is open and in the background.
`ACCESS_COARSE_LOCATION` gives results equal to about a city block.
`ACCESS_FINE_LOCATION` is the most precise location coordinates.
`ACCESS_COARSE_LOCATION` gives results equal to about a city block.

##Main file:

Let’s start by making changes in the `main.dart` file to contain the new `AskForPermission` widget found within `gpsLocation.dart`:

```
import 'package:flutter/material.dart';
import 'package:gpsproject/gpsLocation.dart';
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter GPS Location Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AskForPermission(),
    );
  }
}
```

The `gpsLocation.dart` contains the following code :

```
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:android_intent/android_intent.dart';
import 'package:geolocator/geolocator.dart';
class AskForPermission extends StatefulWidget {
 @override
 _AskForPermissionState createState() => _AskForPermissionState();
}
class _AskForPermissionState extends State<AskForPermission> {
 final PermissionHandler permissionHandler = PermissionHandler();
 Map<PermissionGroup, PermissionStatus> permissions;
void initState() {
  super.initState();
  requestLocationPermission();
  _gpsService();
}
 Future<bool> _requestPermission(PermissionGroup permission) async {
final PermissionHandler _permissionHandler = PermissionHandler();
var result = await _permissionHandler.requestPermissions([permission]);
if (result[permission] == PermissionStatus.granted) {
  return true;
}
return false;
}
/*Checking if your App has been Given Permission*/
Future<bool> requestLocationPermission({Function onPermissionDenied}) async {
var granted = await _requestPermission(PermissionGroup.location);
if (granted!=true) {
  requestLocationPermission();
}
debugPrint('requestContactsPermission $granted');
return granted;
}
/*Show dialog if GPS not enabled and open settings location*/
Future _checkGps() async {
 if (!(await Geolocator().isLocationServiceEnabled())) {
  if (Theme.of(context).platform == TargetPlatform.android) {
showDialog(
   context: context,
   builder: (BuildContext context) {
    return AlertDialog(
     title: Text("Can't get gurrent location"),
     content:const Text('Please make sure you enable GPS and try again'),
     actions: <Widget>[
       FlatButton(child: Text('Ok'),
       onPressed: () {
         final AndroidIntent intent = AndroidIntent(
          action: 'android.settings.LOCATION_SOURCE_SETTINGS');
       intent.launch();
       Navigator.of(context, rootNavigator: true).pop();
       _gpsService();
      })],
     );
   });
  }
 }
}

/*Check if gps service is enabled or not*/
Future _gpsService() async {
if (!(await Geolocator().isLocationServiceEnabled())) {
  _checkGps();
  return null;
} else
return true;
}
@override
Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  title: Text('Ask for permisions'),
  backgroundColor: Colors.red,
 ),
 body: Center(
 child: Column(
 children: <Widget>[
  Text("All Permission Granted"),
 ],
 ))
);
}
}

```

###I hope you have learned something new ! ;)