Listen for navigation events

Your app can listen to events that occur as the user navigates along a route.

Overview

Use the following interfaces to listen for navigation events:

See the code

Detect arrival at a destination

Here, a destination refers to either a final destination or a waypoint. To detect arrival, call Navigator.addArrivalListener(), which registers for a callback when the device reaches a destination.

Upon arrival, the Navigation SDK for Android fires the onArrival() callback and stops the turn-by-turn guidance. You must explicitly call Navigator.continueToNextDestination() to advance to the next waypoint, and Navigator.startGuidance() to continue turn-by-turn navigation.

When you call continueToNextDestination(), the navigator discards all information about the previous destination. If you want to analyze information about the previous route segment, you must retrieve the information from the navigator before calling continueToNextDestination().

To avoid memory leaks, you must call removeArrivalListener(listener) when you no longer need the listener.

mNavigator.addArrivalListener(new Navigator.ArrivalListener() {
    @Override
    public void onArrival(ArrivalEvent arrivalEvent) {
        displayMessage("onArrival: You've arrived at a waypoint: "
                + mNavigator.getCurrentRouteSegment().getDestinationWaypoint().getTitle(),
                DISPLAY_BOTH);
        // Start turn-by-turn guidance for the next leg of the route.
        if (arrivalEvent.isFinalDestination()) {
            displayMessage("onArrival: You've arrived at the final destination.",
                    DISPLAY_BOTH);
        } else {
            mNavigator.continueToNextDestination();
            mNavigator.startGuidance();
        }
    }
});

Receive location updates

Obtain a RoadSnappedLocationProvider from the NavigationApi, then call RoadSnappedLocationProvider.addLocationListener() to register for a callback when the device's location or heading changes. Note that this location is snapped to a road, and so it may be different from the location returned by the fused location provider in the Google Play services location APIs.

The Navigation SDK provides location updates as often as possible. When a location update is available, the Navigation SDK fires the onLocationChanged() callback.

Road-snapped location updates are independent of navigation, and can continue even after navigation has stopped. Subscribing to location updates may cause battery drain, a memory leak, or unintentional collection of device location data if you leave the location updates running in the background. Call RoadSnappedLocationProvider.removeLocationListener when you no longer need the listener.

mRoadSnappedLocationProvider =
        NavigationApi.getRoadSnappedLocationProvider(getApplication());
if (mRoadSnappedLocationProvider != null) {
    mRoadSnappedLocationProvider.addLocationListener(
            new RoadSnappedLocationProvider.LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    displayMessage("onLocationUpdated: Navigation engine has provided a new"
                                    + " road-snapped location: "
                                    + location.toString(),
                            DISPLAY_LOG);
                }
            });
} else {
    displayMessage("ERROR: Failed to get a location provider", DISPLAY_LOG);
}

Receive time and distance updates

Call Navigator.addRemainingTimeOrDistanceChangedListener() to register for a callback when the remaining time (seconds) or distance (meters) changes by more than a given threshold.

When the change in time or distance exceeds the specified amount, the Navigation SDK fires the onRemainingTimeOrDistanceChanged() callback.

To find the remaining time and distance, call Navigator.getTimeAndDistanceList(). Note that the times and distances in the list are cumulative: they show the time and distance from the current location to each waypoint, not from one waypoint to another. The TimeAndDistance object now also returns delaySeverity. This enum will be either heavy, meduim, light, or unknown. This corresponds to the color you see on eta in the maps UI (heavy = red, medium = yellow, light = green). This is helpful if you need to create your own eta footer.

To avoid memory leaks, you must call Navigator.removeRemainingTimeOrDistanceChangedListener(listener) when you no longer need the listener.

The sample below requests a callback if the remaining time changes by more than 60 seconds or the remaining distance changes by more than 100 meters.

mNavigator.addRemainingTimeOrDistanceChangedListener(60, 100,
        new Navigator.RemainingTimeOrDistanceChangedListener() {
            @Override
            public void onRemainingTimeOrDistanceChanged() {
                displayMessage("onRemainingTimeOrDistanceChanged: Time or distance estimate"
                        + " has changed.",
                        DISPLAY_LOG);
            }
        });

You can show remaining time and distance information using the built-in display using the setEtaCardEnabled() method and passing a parameter with the value TRUE. To suppress the time/distance display, set this value to FALSE.

You can also expose the ETA for multiple waypoints using the getTimeAndDistanceList() method.

Receive route updates

Call Navigator.addRouteChangedListener() to register for a callback when the route changes.

When the route changes, the Navigation SDK fires the onRouteChanged() callback. You can call Navigator.getRouteSegments and Navigator.getCurrentRouteSegment() to find the new route.

To avoid memory leaks, you must call removeRouteChangedListener(listener) when you no longer need the listener.

mNavigator.addRouteChangedListener(new Navigator.RouteChangedListener() {
    @Override
    public void onRouteChanged() {
        displayMessage("onRouteChanged: The driver's route has changed. Current waypoint: "
                + mNavigator.getCurrentRouteSegment().getDestinationWaypoint().getTitle(),
                DISPLAY_LOG);
    }
});

Detect when night mode changes

Call NavigationView.addOnNightModeChangedListener or SupportNavigationFragment.addOnNightModeChangedListener to register for a callback when night mode changes.

The following example shows listening for night mode changes on a navigation fragment.

mNavFragment.addOnNightModeChangedListener(new NavigationView.OnNightModeChangedListener() {
    @Override
    public void onNightModeChanged(NightModeChangedEvent nightModeChangedEvent) {
        displayMessage("Night mode is active: " + nightModeChangedEvent.inNightMode(),
        DISPLAY_LOG);
    }
});