# location [![location on pub.dev][location_badge]][location_link] [![code style][leancode_lint_badge]][leancode_lint_link] [![powered by][docs_page_badge]][docs_page_link] [![codecov][codecov_badge]][codecov_link] This plugin for [Flutter](https://flutter.dev) handles getting a location across Android, iOS, macOS, web, Windows and Linux. It also provides callbacks when the location is changed. | Android | iOS | macOS | Web | Windows | Linux | | :-----: | :-: | :---: | :-: | :-----: | :---: | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | Background mode is available on Android and iOS. Windows relies on `Windows.Devices.Geolocation` and Linux on GeoClue2 (over D-Bus); both require the system location service to be enabled.

Youtube Video

[Web demo](https://lyokone.github.io/flutterlocation) (more features available on Android/iOS) ## Getting Started Add this to your package's `pubspec.yaml` file: ```yaml dependencies: location: ^10.0.0 ``` ### Android To use location background mode on Android, you have to use the enableBackgroundMode({bool enable}) API before accessing location in the background and adding necessary permissions. You should place the required permissions in your applications /android/app/src/main/AndroidManifest.xml: ```xml ``` Remember that the user has to accept the location permission to `always allow` to use the background location. The Android 11 option to `always allow` is not presented on the location permission dialog prompt. The user has to enable it manually from the app settings. This should be explained to the user on a separate UI that redirects the user to the app's location settings managed by the operating system. More on that topic can be found on [Android developer](https://developer.android.com/training/location/permissions#request-background-location) pages. ### iOS And to use it in iOS, you have to add this permission in Info.plist : ``` // This is probably the only one you need. Background location is supported // by this -- the caveat is that a blue badge is shown in the status bar // when the app is using location service while in the background. NSLocationWhenInUseUsageDescription // Deprecated, use NSLocationAlwaysAndWhenInUseUsageDescription instead. NSLocationAlwaysUsageDescription // Use this very carefully. This key is required only if your iOS app // uses APIs that access the user’s location information at all times, // even if the app isn't running. NSLocationAlwaysAndWhenInUseUsageDescription ``` To receive location when application is in background, to Info.plist you have to add property list key : ```xml UIBackgroundModes ``` with string value: ```xml location ``` ### Web Nothing to do, the plugin works directly out of box. ### macOS Ensure that the application is properly "sandboxed" and that the location is enabled. You can do this in Xcode with the following steps: 1. In the project navigator, click on your application's target. This should bring up a view with tabs such as "General", "Capabilities", "Resource Tags", etc. 1. Click on the "Capabilities" tab. This will give you a list of items such as "App Groups", "App Sandbox", and so on. Each item will have an "On/Off" button. 1. Turn on the "App Sandbox" item and press the ">" button on the left to show the sandbox stuff. 1. In the "App Data" section, select "Location". Add this permission in Info.plist : ```xml NSLocationWhenInUseUsageDescription NSLocationAlwaysUsageDescription ``` ### Windows Nothing to do. The plugin uses the `Windows.Devices.Geolocation` APIs, which prompt the user for location access on first use. Make sure Location is enabled in the Windows privacy settings. ### Linux The plugin talks to [GeoClue2](https://gitlab.freedesktop.org/geoclue/geoclue) over D-Bus, so a running `geoclue` service is required (it ships with most desktop distributions). No extra dependency needs to be bundled with your app. ## Usage Then you just have to import the package with ```dart import 'package:location/location.dart'; ``` In order to request location, you should always check Location Service status and Permission status manually ```dart Location location = Location(); bool serviceEnabled; PermissionStatus permissionGranted; LocationData locationData; 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; } } locationData = await location.getLocation(); ``` You can also get continuous callbacks when your position is changing: ```dart location.onLocationChanged.listen((LocationData currentLocation) { // Use current location }); ``` To receive location when application is in background you have to enable it: ```dart location.enableBackgroundMode(enable: true) ``` `enableBackgroundMode(enable: true)` is a standalone call: you can invoke it **before** you start listening to `onLocationChanged`. On Android it also requests the `ACCESS_BACKGROUND_LOCATION` permission when it has not been granted yet, so you can use it to prompt for background permission independently, without having to activate a location stream first. **This only keeps tracking location while your app process is alive** — on Android via a foreground service, on iOS via a background execution exemption. Neither survives the user manually killing the app (swiping it away from the recent-apps list) or the OS terminating it outright; there is no way for any Flutter plugin to run Dart code once the process itself no longer exists. If you need tracking that resumes after the app is killed/terminated, look at a plugin built around native background services designed for that, such as [`flutter_background_geolocation`](https://pub.dev/packages/flutter_background_geolocation). Be sure to check the example project to get other code samples. On Android, a foreground notification is displayed with information that location service is running in the background. On iOS, while the app is in the background and gets the location, the blue system bar notifies users about updates. Tapping on this bar moves the User back to the app.

Androig background location iOS background location

## Public Methods Summary | Return | Description | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Future\ | **requestPermission()**
Request the Location permission. Returns a `PermissionStatus` to know if the permission has been granted. | | Future\ | **hasPermission()**
Returns a `PermissionStatus` to know the state of the location permission. | | Future\ | **isBackgroundPermissionGranted()**
Whether background ("Allow all the time"/Always) location access has been granted, separately from foreground access. Always `false` on web. | | Future\ | **serviceEnabled()**
Returns a boolean to know if the Location Service is enabled or if the user manually deactivated it. | | Future\ | **requestService()**
Show an alert dialog to request the user to activate the Location Service. On iOS, will only display an alert due to Apple Guidelines, the user having to manually go to Settings. Returns a boolean to know if the Location Service has been activated (always `false` on iOS). | | Future\ | **changeSettings({accuracy, interval, distanceFilter, pausesLocationUpdatesAutomatically, backgroundInterval})**
Changes the settings of future requests. `interval`/`distanceFilter`/`backgroundInterval` are Android-only; `pausesLocationUpdatesAutomatically` is iOS/macOS-only. See [settings](https://docs.page/Lyokone/flutterlocation/features/settings) for details. | | Future\ | **getLocation()**
Gets a one-time position of the user. Requests permission if not already granted, and throws a `PERMISSION_DENIED` error if permission still isn't granted. | | Future\ | **getLastKnownLocation()**
Returns the most recently cached location immediately (or `null` if none is available), without waiting for a fresh fix. Always `null` on web. | | Stream\ | **onLocationChanged**
Stream of the user's location. Requests permission if not already granted, and throws a `PERMISSION_DENIED` error if permission still isn't granted. | | Future\ | **isBackgroundModeEnabled()**
Checks whether background mode is currently enabled. | | Future\ | **enableBackgroundMode({enable, requireBackgroundPermission})**
Enables or disables retrieving location events in the background (Android/iOS only). `requireBackgroundPermission` (Android only, default `true`) controls whether `ACCESS_BACKGROUND_LOCATION` is required. | | Future\ | **changeNotificationOptions({channelName, title, iconName, imageName, iconBytes, imageBytes, subtitle, description, color, onTapBringToFront})**
Customizes the Android background-mode notification. See [notifications](https://docs.page/Lyokone/flutterlocation/features/notification). | You should try to manage permission manually with `requestPermission()` to avoid error, but plugin will try handle some cases for you. ## Objects ```dart class LocationData { final double latitude; // Latitude, in degrees final double longitude; // Longitude, in degrees final double? accuracy; // Estimated horizontal accuracy of this location, radial, in meters final double? verticalAccuracy; // Estimated vertical accuracy of altitude, in meters final double? altitude; // In meters above the WGS 84 reference ellipsoid final double? speed; // In meters/second final double? speedAccuracy; // In meters/second. Not available on web final double? heading; // Horizontal direction of travel of this device, in degrees final double? time; // Timestamp of the LocationData final bool? isMock; // Is the location currently mocked final bool? isProducedByAccessory; // Whether the fix came from a connected accessory (e.g. external GPS). iOS/macOS only final double? headingAccuracy; // Estimated bearing accuracy, in degrees. Android only final double? elapsedRealtimeNanos; // Time of this fix, in elapsed real-time since system boot. Android only final double? elapsedRealtimeUncertaintyNanos; // Uncertainty of elapsedRealtimeNanos. Android only final int? satelliteNumber; // Number of satellites used to derive the fix. Android only final String? provider; // Name of the provider that generated this fix. Android only } enum LocationAccuracy { powerSave, // To request best accuracy possible with zero additional power consumption low, // To request "city" level accuracy balanced, // To request "block" level accuracy high, // To request the most accurate locations available navigation, // To request location for navigation usage (affects only iOS) reduced, // Maps to kCLLocationAccuracyReduced on iOS 14+; equivalent to `low` elsewhere } // Status of a permission request to use location services. enum PermissionStatus { /// The permission to use location services has been granted for high accuracy. granted, /// The permission has been granted but for low (approximate) accuracy only. grantedLimited, /// The permission to use location services has been denied by the user. May have been denied forever on iOS. denied, /// The permission to use location services has been denied forever by the user. No dialog will be displayed on permission request. deniedForever } ``` `LocationData` also has `toJson()`/`fromJson()` and `copyWith()` for serialization and copying. Note: you can convert the timestamp into a `DateTime` with: `DateTime.fromMillisecondsSinceEpoch(locationData.time!.toInt())` ## Feedback Please feel free to [give me any feedback](https://github.com/Lyokone/flutterlocation/issues) helping support this plugin ! [location_badge]: https://img.shields.io/pub/v/location?label=location [location_link]: https://pub.dev/packages/location [leancode_lint_badge]: https://img.shields.io/badge/code%20style-leancode__lint-black [leancode_lint_link]: https://pub.dev/packages/leancode_lint [docs_page_badge]: https://img.shields.io/badge/documentation-docs.page-34C4AC.svg?style [docs_page_link]: https://docs.page [codecov_badge]: https://codecov.io/gh/Lyokone/flutterlocation/branch/master/graph/badge.svg [codecov_link]: https://codecov.io/gh/Lyokone/flutterlocation