“This is the 15th day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

The geolocator plugin for Flutter is introduced today.

The following content is translated from geolocator pub, the level is limited, we would like to give advice.

geolocator

Geolocator profile

Geolocator is a location plugin for Flutter that provides easy access to platform specific location services.

  • Use FusedLocationProviderClient Android: by default, if not available, use the LocationManager.
  • IOS: CLLocationManager.

features

  • Gets the last known location
  • Gets the current location of the device
  • Gets continuous location updates
  • Check whether the location service of the device is available
  • Calculate the distance between two geographic coordinates (in meters)
  • Compute the bearing between two geographic coordinates

Important: Version 7.0.0 of the Geolocator plugin contains some incompatible changes. For a complete overview, see the Breaking Changes in 7.0.0 wiki. Geocoding features (placemarkFromAddress and placemarkFromCoordinates) are no longer part of Geolocator as of version 6.0.0. These features have been moved to a separate Geocoding plug-in. This new plug-in is an upgrade of the old method.

use

Add the Geolocator plugin to the Flutter application by referring to the installation instructions. To enable the Geolocator plug-in to work properly on various devices, you need to do the following:

Android

Update Android projects prior to 1.12

As of version 5.0.0, the plugin implementation uses the API of the Android plugin for Flutter 1.12. Unfortunately, this means that APP developers will also need to migrate their apps to support the new Android architecture. You can follow the upgrade Pre 1.12 Android Projects migration wizard to start the upgrade. If the migration fails, the use of a new plug-in may result in unexpected behavior.

AndroidX

The Geolocator plugin requires the AndroidX version of the Android Support Libraries. This means making sure your Android project supports AndroidX. Detailed instructions can be found here.

Summary of contents:

  1. togradle.propertiesAdd the following to the file.
android.useAndroidX=true
android.enableJetifier=true
Copy the code
  1. Make sure thatandroid/app/build.gradleIn thecompileSdkVersionSet it to 31.
android {
  compileSdkVersion 31. }Copy the code
  1. Ensure that allandroid.The dependency has been replaced with the corresponding AndroidX version.

    The full list is here:Migrating to AndroidX.

permissions

Add ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION to the Android Manifest. Open the androidmanifest.xml file (location: Android /app/ SRC /main) and add one of the following two lines as a direct child of the

tag. If both permissions are configured, the geolocator plug-in uses the ACCESS_FINE_LOCATION permission.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Copy the code

Starting with Android10, if your APP wants to continuously get updates while it’s running in the background (note that geolocator doesn’t support receiving an in-process location update while running in the background), The ACCESS_BACKGROUND_LOCATION permission needs to be added (under the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission).

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
Copy the code

Note: Specifying the ACCESS_COARSE_LOCATION permission results in location updates with roughly the same precision as a city block. It can take a long time (several minutes) before getting the first location correction, because ACCESS_COARSE_LOCATION only uses the network service to calculate the location of the device. See here for more information.

iOS

In iOS you need to add the following to the info.plist file (location: iOS /Runner) to access the location of the device. Simply put, open the info.plist file and add the following (make sure the description is updated to fit the context of your APP) :

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>
Copy the code

If your APP wants to keep getting updates while it’s running in the background, You need to add Backgroud Modes capability (Project > Signing and Capabilities > “+ Capability” button) and select location updates to the XCode Project. One caveat to this is that when submitting your App to the AppStore, you need to explain to Apple the details of why your App needs to be set this way. If Apple is not satisfied with your explanation, your APP will be rejected.

Using requestTemporaryFullAccuracy ({purposeKey: “YourPurposeKey”}) approach, the need to Info. Add the following dictionary file.

<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
  <key>YourPurposeKey</key>
  <string>The example App requires temporary access to the device&apos;s precise location.</string>
</dict>
Copy the code

The second Key (in this case is YourPurposeKey) and passed to requestTemporaryFullAccuracy purposeKey matching parameters () method. You can also define multiple keys for different features of your APP. More information can be found here.

Note: The first temporary request for full precision access will take a long time to display the confirmation popup. This is because it takes a long time for iOS to confirm the exact location of a user. Unfortunately, this is out of the plug-in’s control.

macOS

In macOS you need to add the following to the info.plist file (location: macOS/Runner) to access the location of the device. Simply put, open the info.plist file and add the following (make sure the description is updated to fit the context of your APP) :

<key>NSLocationUsageDescription</key>
<string>This app needs access to location.</string>
Copy the code

At the same time need in DebugProfile. Entitlements and Release. Add the following entitlements. This is used to declare that the APP wants to use the device’s location service. The APP will be added to the list of system preferences -> Security & Privacy -> Privacy Settings.

<key>com.apple.security.personal-information.location</key>
<true/>
Copy the code

Using requestTemporaryFullAccuracy ({purposeKey: “YourPurposeKey”}) approach, the need to Info. Add the following dictionary file.

<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
  <key>YourPurposeKey</key>
  <string>The example App requires temporary access to the device&apos;s precise location.</string>
</dict>
Copy the code

The second Key (in this case is YourPurposeKey) and passed to requestTemporaryFullAccuracy purposeKey matching parameters () method. You can also define multiple keys for different features of your APP. More information can be found here.

Note: The first temporary request for full precision access will take a long time to display the confirmation popup. This is because it takes a long time for macOS to confirm the exact location of the user. Unfortunately, this is out of the plug-in’s control.

Web

To use the Geolocator plugin on the Web, You need Flutter 1.20 or later. When you add a geolocator: ^6.2.0 dependency to pubspec.yaml, Flutter automatically adds the Geolocator_web package to the application.

The following methods of the Geolocator API are not supported on the Web. If used, a PlatformException with an UNSUPPORTED_OPERATION error code is raised.

  • getLastKnownPosition({ bool forceAndroidLocationManager = true })

  • openAppSettings()

  • openLocationSettings()

    Note: Due to a bug in the DART: HTML library, geolocator for the Web does not work in empty safe mode or compile in Release mode. Running the APP in Release mode raises Uncaught TypeError (Issue #693). The current workaround is to disable null security in release mode to compile.

      flutter build web --no-sound-null-safety --release
    Copy the code

    The Dart team has made this fix (currently available in Dart 2.15.0-63.0.dev) and has of course been released and integrated into Flutter.

The sample

The following code shows how to request the current location of the device, including checking that the location service is available and requesting location permissions to access the device.

import 'package:geolocator/geolocator.dart';

/// Determine the current position of the device.
///
/// When the location services are not enabled or permissions
/// are denied the `Future` will return an error.
/// 
/// Determine the current position of the device
/// Error is returned when the location service is unavailable or permission is denied.
Future<Position> _determinePosition() async {
  bool serviceEnabled;
  LocationPermission permission;

  // Test if location services are enabled.
  // Check whether the location service is available.
  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if(! serviceEnabled) {// Location services are not enabled don't continue
    // accessing the position and request users of the 
    // App to enable the location services.
    // The location service is not available, no further access to the location, and no request to APP users for permission to use the location service.
    return Future.error('Location services are disabled.');
  }

  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {
      // Permissions are denied, next time you could try
      // requesting permissions again (this is also where
      // Android's shouldShowRequestPermissionRationale 
      // returned true. According to Android guidelines
      // your App should show an explanatory UI now.
      / / access is refused, the next will continue to try to request permissions (android shouldShowRequestPermissionRationale will return true.
      // Following android's instructions, the APP will display a screen with instructions.)
      return Future.error('Location permissions are denied'); }}if (permission == LocationPermission.deniedForever) {
    // Permissions are denied forever, handle appropriately. 
    // Permissions are permanently denied, processed appropriately.
    return Future.error(
      'Location permissions are permanently denied, we cannot request permissions.');
  } 

  // When we reach here, permissions are granted and we can
  // continue accessing the position of the device.
  // This indicates that the user is authorized to continue accessing the device location.
  return await Geolocator.getCurrentPosition();
}
Copy the code

API

The geographical position

To query the current location of the device, simply call the getCurrentPosition method. The results can be adjusted using the following parameters:

  • desiredAccuracy: The accuracy of the location data the APP wants to receive.
  • timeLimit: Maximum time for requesting the current location. When this time is exceeded, it throwsTimeOutExceptionException, the call will be cancelled. By default, no timeout period.
import 'package:geolocator/geolocator.dart';

Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
Copy the code

To query the last known location stored on the device, use the getLastKnownPosition method (which returns NULL if no location details are available) :

import 'package:geolocator/geolocator.dart';

Position position = await Geolocator.getLastKnownPosition();
Copy the code

To listen for position changes, you can call getPositionStream to receive a stream used to listen for and receive position updates. The results can be adjusted using the following parameters:

  • desiredAccuracy: The accuracy of the location data the APP wants to receive.
  • distanceFilter: Minimum horizontal movement of the device required to trigger the position update event (in meters)
  • timeInterval: (Android only), the minimum interval required for the next location update event to be triggered.
  • timeLimit: Maximum time allowed between position updates. When this time is exceeded, it throwsTimeOutExceptionException, the flow will be cancelled. By default, no timeout period.
import 'package:geolocator/geolocator.dart';

StreamSubscription<Position> positionStream = Geolocator.getPositionStream(locationOptions).listen(
    (Position position) {
        print(position == null ? 'Unknown' : position.latitude.toString() + ', ' + position.longitude.toString());
    });
Copy the code

To listen for service status, call the getServiceStatusStream method. This method returns a Stream

that can be listened on and then receive updates on the status of the location service.

import 'package:geolocator/geolocator.dart';

StreamSubscription<ServiceStatus> serviceStatusStream = Geolocator.getServiceStatusStream().listen(
    (ServiceStatus status) {
        print(status);
    });
Copy the code

Get position accuracy (Android and iOS 14+ only)

To find out whether the user can get a general location or an exact location, call the Geolocator().getlocationaccuracy () method. This method returns the Future

. When a user can obtain the position of the general, the return value contains LocationAccuracyStatus. Reduced; When a user can obtain precise location, the return value contains LocationAccuracyStatus. Precise. If the call getLocationAccuracy before give user permissions, will return the default LocationAccuracyStatus. Reduced. IOS or lower version 13 getLocationAccuracy will always return LocationAccuracyStatus. Precise, because this is 13 or lower version of the iOS default values.

import 'package:geolocator/geolocator.dart';

var accuracy = await Geolocator.getLocationAccuracy();
Copy the code

To check whether the service location is available, call the isLocationServiceEnabled method:

import 'package:geolocator/geolocator.dart';

bool isLocationServiceEnabled  = await Geolocator.isLocationServiceEnabled();
Copy the code

permissions

Geolocator will automatically try to request permission when you try to get a location using either getCurrentPosition or getPositionStream. Even so, we provide a way to allow permission to be requested manually.

If you want to check whether the user is authorized to obtain a location, you can call the checkPermission method.

import 'package:geolocator/geolocator.dart';

LocationPermission permission = await Geolocator.checkPermission();
Copy the code

If you want to requestPermission to access the device location, you can call the requestPermission method.

import 'package:geolocator/geolocator.dart';

LocationPermission permission = await Geolocator.requestPermission();
Copy the code

The checkPermission and requestPermission methods have the following possible results:

permissions instructions
denied The user has denied access to the device location. Permission can be requested again (this is also the initial permission state)
deniedForever Access to the device location has been permanently denied. The permission dialog box for requesting permission is no longer displayed until the user updates the permission in the APP Settings.
whileInUse Allow access to device locations only when using the APP.
always Allows access to device locations even when the APP is running in the background.

Note: whileInUser, always, or denied will only be returned when checking permissions on Android. This is because on the Android operating system, when checking permissions, it is impossible to confirm whether permissions are permanently denied. The only workaround available is to have the requestPermission method return such a result. More information can be found on our wiki.

set

In some cases, it may be necessary to request permissions from users and update device Settings. For example, the user initially permanently denied access to the device’s location, or the location service was unavailable (and, on Android, automatic resolution didn’t work). In these cases, you can use the openAppSettings or openLocationSettings method to immediately redirect the user to the device Settings screen.

On Android, the openAppSettings method jumps to app-specific Settings, where the user can update the necessary permissions. The openLocationSettings method jumps to location Settings, where the user can allow/disable location services.

On iOS, you are not allowed to open specific Settings, so both methods jump to Settings APP(iOS Settings), where users can browse and modify Settings to update permissions or allow/disable location services.

import 'package:geolocator/geolocator.dart';

await Geolocator.openAppSettings();
await Geolocator.openLocationSettings();
Copy the code

A practical method

To calculate the distance (in meters) between two geographic coordinates, use the distanceBetween method. The method takes four parameters:

parameter type instructions
startLatitude double Latitude of the starting position
startLongitude double The longitude of the starting position
endLatitude double Latitude of the starting position
endLongitude double The longitude of the starting position
import 'package:geolocator/geolocator.dart';

double distanceInMeters = Geolocator.distanceBetween(52.2165157.6.9437819.52.3546274.4.8285838);
Copy the code

To compute the bearingBetween two geographic coordinates, use the bearingBetween method. The method also takes four parameters:

parameter type instructions
startLatitude double Latitude of the starting position
startLongitude double The longitude of the starting position
endLatitude double Latitude of the starting position
endLongitude double The longitude of the starting position
import 'package:geolocator/geolocator.dart'; Double bearing = Geolocator. BearingBetween (52.2165157, 6.9437819, 52.3546274, 4.8285838);Copy the code

Location accuracy

The following table lists the accuracy options for each platform

Android iOS
lowest 500m 3000m
low 500m 1000m
medium 100m – 500m 100m
high 0 – 100m 10m
best 0 – 100m ~0m
bestForNavigation 0 – 100m Optimized for navigation

Contact problem

Submit an issue on our GitHub page if you have any issues, bugs or features to submit. For business support, you can contact us at [email protected].

Intention to contribute

If you want to contribute to the plug-in (for example, improve documentation, fix bugs, or add cool new features), please review our contribution guidelines and send us your pull Request.

The author

The Geolocator plugin for Flutter was developed by Baseflow.