Система геокодирования для определения области в любой точке Земли.

O pen L ocation C ode (OLC) - это система геокодирования, разработанная Google и выпущенная в октябре. 2014. Коды местоположения, созданные системой OLC, называются плюс-кодами. Эти коды поддерживаются поиском Google Maps с августа 2015 года.

Коды Plus предназначены для использования в качестве уличных адресов и могут быть полезны в местах, где нет формальной системы идентификации зданий, например, названия улиц, номера домов и почтовые индексы.

В следующих примерах мы будем использовать глобальную штаб-квартиру Google.

Широта и долгота их штаб-квартиры: 37.422062, -122.08406.

Почтовый адрес: 1600 Amphitheatre Pkwy, Mountain View, CA 94043, США.

Полный плюс-код для того же адреса - 849VCWC8 + R9, а короткий плюс-код - CWC8 + R9, Маунтин-Вью.

Как видите, система OLC помогает нам кодировать местоположение в форму, которую легче использовать и запоминать. По длине его можно сравнить с телефонным номером, но он может стать еще короче, если мы удалим первые 4 символа из полного кода Plus и добавим населенный пункт.

Коды выводятся из координат широты и долготы и могут быть закодированы или декодированы в автономном режиме. Мы не будем вдаваться в технические подробности, и, если вам интересно, спецификацию можно найти здесь.

Также, вот короткое видео о Plus-кодах:

Использование географических координат во Flutter

Чтобы иметь возможность использовать местоположение мобильного устройства во Flutter, вам необходимо импортировать пакет, который это позволяет. Самым популярным на данный момент пакетом такого рода является геолокатор.

Сначала мы добавляем его в список зависимостей нашего приложения внутри файла pubspec.yaml, используя:

dependencies:
  flutter:
     sdk: flutter
  geolocator: ^6.1.13

В зависимости от используемой мобильной платформы вам придется запрашивать разрешения на использование местоположения пользователя.

Для Android необходимо изменить файл AndroidManifest.xml, расположенный в папке android/app/src/main/, и добавить следующие строки вверху справа после корневого узла XML manifest:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

Вы также можете добавить строки. Только убедитесь, что вы не разместили их внутри уже существующего узла activity, иначе вы получите Task 'assembleAarRelease' not found in root project 'geolocator'. ошибку.

Для iOS необходимо изменить файл Info.plist, расположенный в папке ios/Runner/, и добавить следующие строки:

<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>

Для готового к производству приложения объяснение того, почему вам нужен доступ к местоположению, должно быть немного более сложным и просто потому, что не годится. Если вы пойдете по вышеуказанной причине, ваше приложение, вероятно, будет отклонено Apple.

Имея все необходимое, мы, наконец, можем написать код для геолокации.

import 'package:geolocator/geolocator.dart';
...
Future<Position> _getCurrentPosition() async {
    bool serviceEnabled;
    LocationPermission permission;
    serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      return Future.error('Location service disabled.');
    }
    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.deniedForever) {
      return Future.error('Permission permanently denied');
    }
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission != LocationPermission.whileInUse &&
          permission != LocationPermission.always) {
        return Future.error('Permission denied');
      }
    }
    return await Geolocator.getCurrentPosition();
}

Приведенный выше код близок к удобочитаемому. Сначала мы проверяем, включена ли служба определения местоположения. Если он включен, мы удостоверяемся, что нам разрешено его использовать. Наконец, если мы в зеленом, мы вызываем метод getCurrentPosition объекта Geolocator. Это возвращает Position, который имеет свойства latitude и longitude, которые мы искали.

Использование плюсовых кодов во Flutter

Я не нашел ни одного пакета на pub.dev, который имел бы дело с кодами Plus.

Существует пакет геокодирования, который предоставляет функции геокодирования и обратного геокодирования. Геокодирование - это преобразование адресов (например, адреса улицы) в географические координаты (например, широту и долготу). Обратное геокодирование преобразует широту и долготу в адрес. Думаю, в будущем этот пакет может быть расширен.

К счастью, Google предоставляет Dart реализацию открытого кода местоположения. Разработанный Google, он повышает его надежность и надежность.

Поскольку Flutter работает на Dart за кулисами, мы можем использовать его, просто добавив зависимость к нашему pubspec.yaml:

dependencies:
  flutter:
     sdk: flutter
  geolocator: ^6.1.13
  open_location_code:
    git:
      url: git://github.com/google/open-location-code.git
      path: dart

После добавления любой новой зависимости вы всегда должны запускать flutter pub get. Обратите внимание, что горячая перезагрузка может привести к сбою, если вы добавите зависимости и попытаетесь использовать их во время работы приложения.

Код, который будет кодировать и декодировать наши географические координаты в Plus Code:

import 'package:open_location_code/open_location_code.dart' as olc;
...
String _getPlusCode(Position fromPosition) {
  return olc.encode(from.latitude, from.longitude, codeLength: 12);
}

Position _getPosition(String fromPlusCode) {
  olc.CodeArea ca = olc.decode(from);
  Position position = Position(latitude: ca.center.latitude, longitude: ca.center.longitude);
  return position;
}

При такой кодировке мы теряем некоторые данные вроде altitude. Мы также теряем некоторую точность, как вы увидите ниже.

Для декодирования нам придется работать с некоторыми CodeArea объектами. Они хранят значения широты и долготы в свойстве center. Скорее всего, это центр прямоугольной области, которую определяет код.

Чтобы завершить и использовать определенные выше методы, мы сделаем что-то вроде:

void _locateMe() async {
  Position position = await _getCurrentPosition();
  print('${position.latitude},${position.longitude}');
  String plusCode = _getPlusCode(pos);
  print(plusCode);
  Position posDecoded = _getPosition(plusCode);
  print('${posDecoded.latitude},${posDecoded.longitude}');
}

Если бы мы сидели в глобальной штаб-квартире Google, вызов вышеуказанного метода выдал бы:

37.422062,-122.08406
849VCWC8+R9GC
37.422062499999996,-122.08405859375

В первой строке мы видим географическую широту и долготу нашего устройства. Во второй строке находится код «Плюс» из 12 символов. В последней строке указаны координаты, декодированные с помощью Plus-кода.

Обратите внимание, что входные координаты не совпадают с декодированными. Это из-за точности кода Plus. По умолчанию длина закодированного кода равна 10. На этой длине область, представленная кодом, составляет ~ 13,5x13,5 метров (около 45x45 футов). Чем больше длина, тем выше точность. Коды длиной более 14 считаются субсантиметровыми. С современной технологией GPS эти длины кажутся пригодными только теоретически.

Вот полный код Dart для вышеуказанного приложения:

Выводы

Итак, вот оно. Мы получили географические координаты, закодировали их в Plus Code и декодировали обратно.

Коды Plus или Open Location Codes весьма полезны, и хотя они существуют уже почти 5 лет, я слышал о них только в прошлом году.

Я планирую вскоре использовать эти коды в проекте Flutter, и их использование не будет тем, для чего их разработал Google. Если вы хотите узнать больше, следите за мной.

Это все!

Следите за сообществом Flutter в Твиттере: https://www.twitter.com/FlutterComm