Open Location Code in Flutter
A geocode system for identifying an area anywhere on the Earth

The Open Location Code (OLC) is a geocoding system developed by Google that was released in October 2014. Location codes created by the OLC system are referred to as Plus Codes. These codes are supported by Google Maps search since August 2015.
Plus Codes are designed to be used like street addresses and can be useful in places where there is no formal system to identify buildings, such as street names, house numbers, and postcodes.
In the following examples, we'll use Google's global headquarters location.
The latitude and longitude for their headquarters are 37.422062, -122.08406.
The mail address is 1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA.
The full Plus Code for the same address is 849VCWC8+R9, and the short Plus Code is CWC8+R9, Mountain View.
As you can see, the OLC system helps us encode a location into a form that is easier to use and remember. It can be compared with a telephone number when it comes to its length, but it can even shorter if we strip the first 4 characters from a full-length Plus Code and add a locality.
The codes are derived from latitude and longitude coordinates and can be encoded or decoded offline. We won't go into further technical details and, if you're curious, the specification can be found here.
Also, here is a short video about Plus Codes:
Using geographic coordinates in Flutter
To be able to use the mobile device location in Flutter you'll need to import a package that enables that. Currently, the most popular package of that kind is geolocator.
We first add it to our app's dependencies list inside the pubspec.yaml
file using:
dependencies:
flutter:
sdk: flutter
geolocator: ^6.1.13
Depending on the mobile platform you use, you'll have to request permissions for using a user's location.
For Android, you have to modify the AndroidManifest.xml
file located under android/app/src/main/
and add the following lines at the top right after the XML's manifest
root node:
<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" />
You can also append the lines. Just make sure you don't place them inside the already present activity
node, otherwise you'll get a Task 'assembleAarRelease' not found in root project 'geolocator'.
error.
For iOS, you have to modify the Info.plist
file located under ios/Runner/
and add the following lines:
<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>
For a production-ready app the explanation of why you need to access the location must be a bit more elaborate and "just-because" won't do. If you go with the above reason, your app will probably be rejected by Apple.
Having all things in place, we can finally write some code to be geolocated.
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();
}
The above code is close to being human-readable. We first check if the location service is enabled. If it is enabled we make sure we're allowed to use it. Finally, if we're in the green, we call the getCurrentPosition
method of the Geolocator
object. That returns a Position
that has the latitude
and longitude
properties we were after.

Using Plus Codes in Flutter
I didn't find any package on pub.dev that deals with the Plus Codes.
There is a geocoding package that provides "geocoding and reverse-geocoding features". Geocoding is converting addresses (like a street address) into geographic coordinates (like latitude and longitude). Reverse-geocoding converts latitude and longitude into an address. I suppose, in the future, this package can be extended.
Fortunately, Google provides a Dart implementation of Open Location Code. Being developed by Google it adds to its reliability and trustworthiness.
Because Flutter runs on Dart behind the scenes we can use it just by adding the dependency to our 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
After adding any new dependency you should always run flutter pub get
. Note that hot reload might crash if you add dependencies and try to use them while the app is running.
The code that will encode and decode our geographic coordinates into a Plus Code is:
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;
}
With this encoding, we lose some data like altitude
. We also lose some precision, as you'll see below.
For decoding, we'll have to work with some CodeArea
objects. They store the latitude and longitude values in a property called center
. Most likely as being the center of the rectangular area the code defines.
To wrap up and use the above-defined methods we'll do something like:
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}');}
If we were to sit in Google's global headquarters, calling the above method would output:
37.422062,-122.08406
849VCWC8+R9GC
37.422062499999996,-122.08405859375
On the first line, we can see our device's geographic latitude and longitude. On the second line, there is a Plus Code with 12 characters. On the last line, there are the coordinates decoded from the Plus Code.
Note that the input coordinates are not the same as the decoded ones. That is because of the precision of a Plus Code. By default, the length of an encoded code is 10. On this length, the area represented by a code is ~13.5x13.5 meters (about 45x45 feet). The higher the length, the higher the precision. Codes with lengths greater than 14 are sub-centimeter. With current GPS technology, these lengths seem usable only in theory.

Here is the full Dart code for the above app:
Conclusions
So here we have it. We got the geographic coordinates, encoded them into a Plus Code, and decoded them back.
Plus Codes or Open Location Codes are quite useful and although they were around for almost 5 years now, I heard of them only last year.
I'm planning of using these codes soon in a Flutter project and their use won't be what Google designed them for. If you're interested in finding more, keep an eye on me.
Tha(nk|t’)s all!
Follow Flutter Community on Twitter: https://www.twitter.com/FlutterComm