Adding Route Paths (Polylines) Between two Points to Google Maps in Flutter

olayemii

OLayemii

Posted on January 30, 2021

Adding Route Paths (Polylines) Between two Points to Google Maps in Flutter

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

google_maps_flutter

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.

You can also check this article 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

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

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

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:



<manifest ...
  <application ...
    <meta-data android:name="com.google.android.geo.API_KEY" 
android:value="YOUR KEY HERE"/>


Enter fullscreen mode Exit fullscreen mode

On iOS

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



#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


Enter fullscreen mode Exit fullscreen mode

Or in your swift code, specify your API key in the application delegate ios/Runner/AppDelegate.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)
  }
}


Enter fullscreen mode Exit fullscreen mode

Adding Google Maps to Our Flutter Application



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


Enter fullscreen mode Exit fullscreen mode

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

Alt Text

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';{% raw %}
``
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 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);
Enter fullscreen mode Exit fullscreen mode

}
`

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 markers = {};

PolylinePoints polylinePoints = PolylinePoints();
Map polylines = {};

class _MyAppState extends State {
// Google Maps controller
Completer _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();
Enter fullscreen mode Exit fullscreen mode

}
@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.of(polylines.values),
markers: Set.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 polylineCoordinates) {
PolylineId id = PolylineId("poly");
Polyline polyline = Polyline(
polylineId: id,
points: polylineCoordinates,
width: 8,
);
polylines[id] = polyline;
setState(() {});
}

void _getPolyline() async {
List 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);
Enter fullscreen mode Exit fullscreen mode

}
}
`

Alt Text

This is a link to a gist with complete code

💖 💪 🙅 🚩
olayemii
OLayemii

Posted on January 30, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related