Adding Route Paths (Polylines) Between two Points to Google Maps in Flutter
Tags: flutter, google, maps, polylines
Published: 2021-01-30 17:08:24

---
title: Adding Route Paths (Polylines) Between two Points to Google Maps in Flutter
published: true
description: 
tags: flutter, google, maps, polylines
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/pfv79g75lhysw7ehr1qf.png
---

Recently, I was working on a flutter project which requires maps and route lines showing the path between two coordinates (the source and destination coordinates).

In this tutorial, I will show you how I was able to achieve this  using this two packages from [pub.dev](https://pub.dev)

> [google_maps_flutter](https://pub.dev/packages/google_maps_flutter)

> [flutter_polyline_points](https://pub.dev/packages/flutter_polyline_points)

After installing this packages, we need to create a google project and get a Google Maps API key from the [Google Developer Console](https://console.cloud.google.com/google/maps-apis).

You can also check this [article](https://developers.google.com/maps/documentation/maps-static/get-api-key) on how to get an api key. 

We also need to activate the following services on the developer console for our Google project:

* Maps SDK for Android
* Maps SDK for iOS
* Directions API

<small>_This can be done by clicking on the search icon on the app bar of the developer console and searching for this services then activating them_</small>

Lastly, we need to setup billing for our project, the Directions API which does the route generation requires billing to work. Though you won't be charged without activating auto charge after your free trial.

You can read this article on [How to Setup Billing For Your Google Developer Account](https://support.google.com/googleapi/answer/6158867?hl=en)

We now need to setup Google maps for our flutter project. 

#### On Android 
Specify your API key in the application manifest `android/app/src/main/AndroidManifest.xml`:
```java
<manifest ...
  <application ...
    <meta-data android:name="com.google.android.geo.API_KEY" 
android:value="YOUR KEY HERE"/>
```

#### On iOS

Specify your API key in the application delegate `ios/Runner/AppDelegate.m`:

```c
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import "GoogleMaps/GoogleMaps.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GMSServices provideAPIKey:@"YOUR KEY HERE"];
  [GeneratedPluginRegistrant registerWithRegistry:self];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
```

Or in your swift code, specify your API key in the application delegate `ios/Runner/AppDelegate.swift`:

```swift 

import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GMSServices.provideAPIKey("YOUR KEY HERE")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}
```

# Adding Google Maps to Our Flutter Application


```dart
import 'dart:async';

import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

// Starting point latitude
  double _originLatitude = 6.5212402;
// Starting point longitude
  double _originLongitude = 3.3679965;
// Destination latitude
  double _destLatitude = 6.849660;
// Destination Longitude
  double _destLongitude = 3.648190;
// Markers to show points on the map
  Map<MarkerId, Marker> markers = {}; 

class _MyAppState extends State<MyApp> {
  // Google Maps controller
  Completer<GoogleMapController> _controller = Completer();
  // Configure map position and zoom
  static final CameraPosition _kGooglePlex = CameraPosition(
    target: LatLng(_originLatitude, _originLongitude),
    zoom: 9.4746,
  ); 

  @override
  void initState() {
    /// add origin marker origin marker
    _addMarker(
      LatLng(_originLatitude, _originLongitude),
      "origin",
      BitmapDescriptor.defaultMarker,
    );

    // Add destination marker
    _addMarker(
      LatLng(_originLatitude, _originLongitude),
      "destination",
      BitmapDescriptor.defaultMarkerWithHue(90),
    );
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: GoogleMap(
            mapType: MapType.normal,
            initialCameraPosition: _kGooglePlex,
            myLocationEnabled: true,
            tiltGesturesEnabled: true,
            compassEnabled: true,
            scrollGesturesEnabled: true,
            zoomGesturesEnabled: true,
            markers: Set<Marker>.of(markers.values),
            onMapCreated: (GoogleMapController controller) {
              _controller.complete(controller);
            },
       ), 
      ),
    );
  }
  
  // This method will add markers to the map based on the LatLng position
  _addMarker(LatLng position, String id, BitmapDescriptor descriptor) {
    MarkerId markerId = MarkerId(id);
    Marker marker =
        Marker(markerId: markerId, icon: descriptor, position: position);
    markers[markerId] = marker;
  }
}
```

This should render google maps with two markers at the origin and destination coordinates.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ssp8bbn4mrd0nlqkygve.png)


# Adding Polylines Between the Locations on Our Map

Now all we need to do is add the polylines to show the path between our point. To do this we make use of the `flutter_polyline_points` package

Add ```dart
import 'package:flutter_polyline_points/flutter_polyline_points.dart';`
```
to the imports at the top of the file.

Next, we need to define a variable to store the polylines we will later query for, and create a PolylinePoints object too.

Add this among other class properties we defined earlier

```dart
  PolylinePoints polylinePoints = PolylinePoints();
  Map<PolylineId, Polyline> polylines = {};
```

Next, we need to write a method to help us query the directions API for the points of the polyline

```dart
    void _getPolyline() async {
    List<LatLng> polylineCoordinates = [];

    PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
      Constants.API_KEY,
      PointLatLng(_originLatitude, _originLongitude),
      PointLatLng(_destLatitude, _destLongitude),
      travelMode: TravelMode.driving,
    );
    if (result.points.isNotEmpty) {
      result.points.forEach((PointLatLng point) {
        polylineCoordinates.add(LatLng(point.latitude, point.longitude));
      });
    } else {
      print(result.errorMessage);
    }
    _addPolyLine(polylineCoordinates);
  }
```

We referenced a `_addPolyLine` function from the `_getPolyline` function, the `_addPolyLine` will help us populate the maps with the polyline points. Let's create this method too

```dart
  _addPolyLine(List<LatLng> polylineCoordinates) {
    PolylineId id = PolylineId("poly");
    Polyline polyline = Polyline(
      polylineId: id,
      color: Constants.primaryColorSwatch,
      points: polylineCoordinates,
      width: 8,
    );
    polylines[id] = polyline;
    setState(() {});
  }
```

Then we add the `polylines` object to our `GoogleMap` property

```dart
   polylines: Set<Polyline>.of(polylines.values),
```

This is the final code 

```dart
import 'dart:async';

import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

// Starting point latitude
  double _originLatitude = 6.5212402;
// Starting point longitude
  double _originLongitude = 3.3679965;
// Destination latitude
  double _destLatitude = 6.849660;
// Destination Longitude
  double _destLongitude = 3.648190;
// Markers to show points on the map
  Map<MarkerId, Marker> markers = {}; 

  PolylinePoints polylinePoints = PolylinePoints();
  Map<PolylineId, Polyline> polylines = {};

class _MyAppState extends State<MyApp> {
  // Google Maps controller
  Completer<GoogleMapController> _controller = Completer();
  // Configure map position and zoom
  static final CameraPosition _kGooglePlex = CameraPosition(
    target: LatLng(_originLatitude, _originLongitude),
    zoom: 9.4746,
  ); 

  @override
  void initState() {
    /// add origin marker origin marker
    _addMarker(
      LatLng(_originLatitude, _originLongitude),
      "origin",
      BitmapDescriptor.defaultMarker,
    );

    // Add destination marker
    _addMarker(
      LatLng(_destLatitude, _destLongitude),
      "destination",
      BitmapDescriptor.defaultMarkerWithHue(90),
    );

    _getPolyline();

    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: GoogleMap(
            mapType: MapType.normal,
            initialCameraPosition: _kGooglePlex,
            myLocationEnabled: true,
            tiltGesturesEnabled: true,
            compassEnabled: true,
            scrollGesturesEnabled: true,
            zoomGesturesEnabled: true,
            polylines: Set<Polyline>.of(polylines.values),
            markers: Set<Marker>.of(markers.values),
            onMapCreated: (GoogleMapController controller) {
              _controller.complete(controller);
            },
       ), 
      ),
    );
  }
  
  // This method will add markers to the map based on the LatLng position
  _addMarker(LatLng position, String id, BitmapDescriptor descriptor) {
    MarkerId markerId = MarkerId(id);
    Marker marker =
        Marker(markerId: markerId, icon: descriptor, position: position);
    markers[markerId] = marker;
  }

_addPolyLine(List<LatLng> polylineCoordinates) {
    PolylineId id = PolylineId("poly");
    Polyline polyline = Polyline(
      polylineId: id,
      points: polylineCoordinates,
      width: 8,
    );
    polylines[id] = polyline;
    setState(() {});
  }

void _getPolyline() async {
    List<LatLng> polylineCoordinates = [];

    PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
      "YOUR API KEY HERE",
      PointLatLng(_originLatitude, _originLongitude),
      PointLatLng(_destLatitude, _destLongitude),
      travelMode: TravelMode.driving,
    );
    if (result.points.isNotEmpty) {
      result.points.forEach((PointLatLng point) {
        polylineCoordinates.add(LatLng(point.latitude, point.longitude));
      });
    } else {
      print(result.errorMessage);
    }
    _addPolyLine(polylineCoordinates);
  }
}
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pfv79g75lhysw7ehr1qf.png)

This is a [link to a gist with complete code](https://gist.github.com/OLayemii/43bbedc0716d3b66bbd7e8577bcc8580)