What is custom navigation?

A custom navigation experience might mean anything from an app that eliminates turn guidance entirely with navigation only as a background process, to an app that projects highly customized guidance to a screen separate from the device that runs the navigator.

What is the custom navigation experience?

  • Start navigation—you create a navigation session. As with the Google navigation experience, a custom navigation experience still involves creating a navigation instance and setting the destination. However, with a customized navigation experience, you achieve this by first establishing a navigation session using GMSNavigationServices. A navigation session is a state-bearing non-UI object that can operate either with a view controller, or without one.

    See the demo: The download of the Navigation SDK contains a demo you can run to see an example of a navigation experience that switches between turn-by-turn guidance through standard navigation to a navigation experience that shows only the device location moving along a road polyline.

  • Active navigation—you provide. Here is another key difference between a Google-provided navigation experience and a custom navigation experience. Instead of handing off guidance to the built-in event manager of the Navigation SDK, you enable the turn-by-turn feed and implement event handlers through the GMSNavigatorListener. This allows your experience to respond to the events described in Listen for navigation events.

  • End navigation—you provide. As with the Google navigation experience, custom navigation also requires you to terminate navigation in the manner best suited for the app's experience.

The following table describes some custom navigation scenarios.

Example scenario

High-level steps

You need to provide text-only driver guidance for small devices such as 2-wheeled vehicles.

Create your navigator and set up the turn-by-turn guidance as a data feed to a small screen device while the navigator runs on the driver's cell phone outside the their immediate view. See Enable turn-by-turn data feed.

Drivers using your app want an overview map for most of their journey, with only minimal turn-by-turn guidance for city streets.

Your app should allow drivers to enter and exit the Google navigation experience as they need, without alternating the navigator's settings for destination and trip mode.

For Mobility Services customers: Drivers often travel established routes with high familiarity and need no guidance at all, but you need a way to ensure your vehicle management system can manage deliveries or trips.

Set up a navigator. Set the destination and get location updates. Integrate the Driver SDK to your app. For details, see Getting started with the Driver SDK for On-demand Rides and Deliveries or Last Mile Fleet Solution.

Create customized guidance

This section covers the high-level steps you follow to create customized guidance.

This process differs from the process described in Navigate a route as follows:

  • You first establish a navigation session independently and obtain a navigator instance through the session rather than by calling the view controller.
  • You set up an event listener to respond to and manage navigation events.

  1. Create a navigation session using GMSNavigationService.createNavigationSession and begin navigation with a setDestination call. Where the Google navigation experience invokes the navigator via the navigation map view, the GMSNavigationServices controls and receives a stream of events from a navigation session independently from a UI instance. This means it can either run without a UI, or get passed to any UI-based experience. With this approach, the navigation session continues to run in your app until the last reference is removed from it.
  2. Establish a road-snapped location provider. Use the location provider if you want your app to have continuous location monitoring, such as when displaying a navigation view with a blue dot along the route.
  3. Set up a listener for detailed turn-by-turn guidance by implementing the GMSNavigatorListener protocol. Then, transform that information into whatever is needed for your custom navigation experience. For example:
    1. Implement text-only fields for simple screen casting of directions.
    2. Design and populate fields for your own UI.
  4. Set up a navigation simulator. This is necessary for development and testing.

Create an independent navigation session

The following code snippets from the demo shows navigation established independently from the view controller. The code then adds an overview map configured to show the current road-snapped location.

// Create the navigation session.

 _navigationSession = [GMSNavigationServices createNavigationSession];
 GMSRoadSnappedLocationProvider *roadSnappedLocationProvider =
     _navigationSession.roadSnappedLocationProvider;
 [roadSnappedLocationProvider startUpdatingLocation];
 GMSNavigator *navigator = _navigationSession.navigator;
 [navigator addListener:self];
 navigator.voiceGuidance = GMSNavigationVoiceGuidanceSilent;
 navigator.sendsBackgroundNotifications = NO;
 _navigationSession.started = YES;
​​ [navigator setDestinations:@[ destination ]
                   callback:^(GMSRouteStatus routeStatus) {
                      // …handle changes in route status.
                    }];

 // Add an overview map.
 _mapView = [[GMSMapView alloc] initWithFrame:CGRectZero];
 [self.mainStackView addArrangedSubview:_mapView];
 [self.mainStackView setNeedsLayout];
 _mapView.settings.compassButton = YES;
 _mapView.delegate = self;
 _mapView.myLocationEnabled = YES;
 _mapView.roadSnappedMyLocationSource = roadSnappedLocationProvider;

Passing navigation from a custom experience to the Google experience

This code snippet illustrates how your app can allow the user to enter the Google navigation experience from a custom navigation experience. This code snippet also shows how your app makes this transition while sharing the map.

`UIButton *button = [UIButton buttonWithType:UIButtonTypePlain`];

[`button addTarget:self action:@selector(didTapEnterGoogleNavigationButton:)
forControlState:[_directionsButton addTarget:self`];

`…`

[`_mapView enableNavigationWithSession:_navigationSession`];