A turn-by-turn data feed provides navigation-only information to devices not
designed for map-based navigation guidance. It provides upcoming maneuvers with
elements you supply:

- icons (left, right, U-turn)
- turn numbers in roundabouts
- road names
- estimated distances and time to the next navigation step or final destination

You can use the turn-by-turn feed to create experiences where the full
Navigation SDK UI is not appropriate, such as for Android Auto or for small
screen displays where a full Android stack is not available. For example, you
might use this for two-wheeled vehicle drivers, where you can project
navigation-only guidance to help them reach their destinations faster and more
confidently with minimal distractions.

To use the SDK, you'll create a service and register it with the
Navigation SDK for Android so that it can receive new navigation information
in real time (about once a second during navigation).

This document shows you how to create and register a navigation service that
receives navigation information from the SDK and provides the navigation state
to the receiving device.

## Overview

This section summarizes the high-level flow for enabling the
turn-by-turn feature.

### Using the TurnByTurn feature

Here are the high-level steps for enabling the turn-by-turn feature. The
sections that follow provide details about each step.

1. [Create a service to receive navigation updates](https://developers.google.com/maps/documentation/navigation/android-sdk/tbt-feed#service).

2. [Register the service](https://developers.google.com/maps/documentation/navigation/android-sdk/tbt-feed#register).

3. [Understand navigation states](https://developers.google.com/maps/documentation/navigation/android-sdk/tbt-feed#states).

## Create a service to receive navigation updates

The Navigation SDK binds to your TurnByTurn service and
sends it navigation updates through the [Android
Messenger](https://developer.android.com/reference/android/os/Messenger)
. You can create a new navigation service for these updates, or use an existing
service.

The benefit of using a service to receive navigation updates is that the service
can live in a separate background process.

The service in the following example receives navigation information and uses
the `TurnByTurnManager` to convert the data into a `NavInfo` object that
contains the navigation details.

```
/**
 *   Receives turn-by-turn navigation information forwarded from NavSDK.
 */
public class NavInfoReceivingService extends Service {
  /** The messenger used by the service to receive nav step updates. */
  private Messenger incomingMessenger;
  private TurnByTurnManager turnByTurnManager;

  private final class IncomingNavStepHandler extends Handler {
    public IncomingNavStepHandler(Looper looper) {
      super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
      // Identify the message through the msg.what field.
      if (TurnByTurnManager.MSG_NAV_INFO == msg.what) {
        // Extract the NavInfo object using the TurnByTurnManager.
        NavInfo navInfo = turnByTurnManager
          .readNavInfoFromBundle(msg.getData()));
      // Do something with the NavInfo
    }
  }
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
  return incomingMessenger.getBinder();
}

@Override
public void onCreate() {
  turnByTurnManager = TurnByTurnManager.createInstance();
  HandlerThread thread =
    new HandlerThread("NavInfoReceivingService",
      Process.THREAD_PRIORITY_DEFAULT);
  thread.start();
  incomingMessenger = new Messenger(
    new IncomingNavStepHandler(thread.getLooper()));
}
```

### Message codes

`NavInfo` messages can be identified through the
[Message.what](https://developer.android.com/reference/android/os/Message#what)
field of the `Message` class, which is set to the value of
`TurnByTurnManager.MSG_NAV_INFO`.

> [!NOTE]
> **Note:** Be sure to aside the value range 7200-7299 for message codes, because the Navigation SDK might use message codes in that range in the future.

## Registering the service for navigation updates

The following code snippets registers the navigation service.

```
boolean isNavInfoReceivingServiceRegistered =
          navigator.registerServiceForNavUpdates(
              getPackageName(), NavInfoReceivingService.class.getName(), numNextStepsToPreview);
```

### Starting and stopping the service

The navigation service is active as long as the
Navigation SDK binds to it. You can manually call
`startService()` and `stopService()` to control the navigation service
lifecycle, but when you register your service with the
Navigation SDK, your service starts automatically, and
only stops when you unregister it. Depending on how you set up your app, you may
want to consider starting a foreground service, described in the Android
documentation [Services
overview](https://developer.android.com/guide/components/services).

### Unregistering the service

To stop receiving navigation updates, unregister the service from the
Navigation SDK.

```
navigator.unregisterServiceForNavUpdates();
```

## Understand navigation states

Use `NavInfo.getNavState()` to get the current state of navigation, which is one
of the following:

- **Enroute** - The `ENROUTE` state means that guided navigation is
  active and the user is on the provided route. Information about the current
  upcoming maneuver step is available.

- **Rerouting** - `REROUTING` means that navigation is in progress, but the
  navigator is looking for a new route. The upcoming maneuver step is not
  available, because there's no new route yet. In the [sample app](https://github.com/googlemaps-samples/android-navigation-samples), a "Rerouting..." message appears in
  the navigation info display. Once a route is found, a `NavInfo` message is
  sent with the state `ENROUTE`.

- **Stopped** - `STOPPED` means navigation has ended. For example, navigation
  stops when the user exits navigation in the app. In the sample app, a
  `STOPPED` state clears the navigation info display to prevent lingering step
  instructions from being displayed.

## Populate the feed display

Now that you have set up your turn-by-turn service, this section covers the
visual and text elements you can use to populate the guidance cards for the
turn-by-turn feed.

### Navigation card information fields

![A mobile screen that displays an upcoming left turn in 100 feet onto W Ahwanee
Ave. At the bottom of the screen, time remaining to destination is 46 minutes,
and distance remaining is 39
miles.](https://developers.google.com/static/maps/documentation/navigation/android-sdk/images/turnbyturn.png)

When the user enters guided navigation, a navigation card appears at the top,
containing navigation data populated from the
Navigation SDK. The related image shows an example of
these essential navigation elements.

This table shows the fields for navigation info and where you find them.

| Fields for each navigation step | Fields for the overall trip |
|---|---|
| Found in `StepInfo` | Found in `NavInfo` |
| Full road name | Remaining time |
| The maneuver icon | Distance to destination |
| Distance to the next step |   |
| Lane guidance fields |   |

#### Lane guidance

The Navigation SDK represents lanes in the navigation
turn card as
[Lane](https://developers.google.com/maps/documentation/navigation/android-sdk/reference/com/google/android/libraries/mapsplatform/turnbyturn/model/Lane)
and
[LaneDirection](https://developers.google.com/maps/documentation/navigation/android-sdk/reference/com/google/android/libraries/mapsplatform/turnbyturn/model/LaneDirection)
data objects. A `Lane` object represents a specific lane during navigation and
has a list of `LaneDirection` objects which describe all the turns that can be
made from this lane.

![A sample lane guidance
configuration.](https://developers.google.com/static/maps/documentation/navigation/android-sdk/images/LaneGuidanceSample.png)

The recommended direction a user should take in a lane is marked by the
[isRecommended](https://developers.google.com/maps/documentation/navigation/android-sdk/reference/com/google/android/libraries/mapsplatform/turnbyturn/model/LaneDirection#isRecommended())
field.

##### Lane guidance example

The following snippet illustrates the data representation of the lanes displayed
above.

    // Lane 1
    LaneDirections = [{/*laneShape=*/ STRAIGHT, /*isRecommended=*/ false},
                      {/*laneShape=*/ SLIGHT_LEFT, /*isRecommended=*/ true}]

    // Lane 2
    LaneDirections = [{/*laneShape=*/ STRAIGHT, /*isRecommended=*/ false}]

### Create icons for maneuvers

The
[`Maneuver`](https://developers.google.com/maps/documentation/navigation/android-sdk/reference/com/google/android/libraries/mapsplatform/turnbyturn/model/Maneuver)
enum defines each possible maneuver that could occur while navigating, and you
can get the maneuver for a given step from the `StepInfo.getManeuver()` method.

You must create maneuver icons and pair them with their associated maneuvers.
For some maneuvers, you can set up a one-to-one mapping to an icon, such as
`DESTINATION_LEFT` and `DESTINATION_RIGHT`. However, since some maneuvers are
similar, you might want to map more than one maneuver to a single icon. For
example `TURN_LEFT` and `ON_RAMP_LEFT` could both map to the left turn icon.

> [!NOTE]
> **Android Auto maneuvers** : Maneuvers in the Navigation SDK have a one-to-one mapping to Android Auto, but you must convert the types to the correct format for Android Auto. See [Verify correct maneuver types](https://developers.google.com/maps/documentation/navigation/android-sdk/android-auto#ensure_correct_maneuver_types) in **Enable navigation for Android Auto**.

Some maneuvers contain an additional `clockwise` or `counterclockwise` label,
which the SDK determines based on the driving side of a country. For example, in
countries where driving is on the left side of the road, drivers take a
roundabout or U-turn in a clockwise direction, whereas right-side-of-the-road
countries go clockwise. The Navigation SDK detects
whether a maneuver occurs in left- or right-side traffic and outputs the
appropriate maneuver. Therefore, your maneuver icon may be different for a
clockwise versus a counterclockwise maneuver.

#### Expand to see examples icons for different maneuvers

| Sample Icon | TurnByTurn Maneuvers |
|---|---|
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_depart.png) | `DEPART` `UNKNOWN` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_straight.png) | `STRAIGHT` `ON_RAMP_UNSPECIFIED` `OFF_RAMP_UNSPECIFIED` `NAME_CHANGE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_right.png) | `TURN_RIGHT` `ON_RAMP_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_left.png) | `TURN_LEFT` `ON_RAMP_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_slight_right.png) | `TURN_SLIGHT_RIGHT` `ON_RAMP_SLIGHT_RIGHT` `OFF_RAMP_SLIGHT_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_slight_left.png) | `TURN_SLIGHT_LEFT` `ON_RAMP_SLIGHT_LEFT` `OFF_RAMP_SLIGHT_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_sharp_right.png) | `TURN_SHARP_RIGHT` `ON_RAMP_SHARP_RIGHT` `OFF_RAMP_SHARP_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_sharp_left.png) | `TURN_SHARP_LEFT` `ON_RAMP_SHARP_LEFT` `OFF_RAMP_SHARP_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_u_turn_counterclockwise.png) | `TURN_U_TURN_COUNTERCLOCKWISE` `ON_RAMP_U_TURN_COUNTERCLOCKWISE` `OFF_RAMP_U_TURN_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_turn_u_turn_clockwise.png) | `TURN_U_TURN_CLOCKWISE` `ON_RAMP_U_TURN_CLOCKWISE` `OFF_RAMP_U_TURN_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_sharp_right_counterclockwise.png) | `ROUNDABOUT_SHARP_RIGHT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_sharp_right_clockwise.png) | `ROUNDABOUT_SHARP_RIGHT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_right_counterclockwise.png) | `ROUNDABOUT_RIGHT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_right_clockwise.png) | `ROUNDABOUT_RIGHT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_slight_right_counterclockwise.png) | `ROUNDABOUT_SLIGHT_RIGHT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_slight_right_clockwise.png) | `ROUNDABOUT_SLIGHT_RIGHT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_straight_counterclockwise.png) | `ROUNDABOUT_STRAIGHT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_straight_clockwise.png) | `ROUNDABOUT_STRAIGHT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_slight_left_counterclockwise.png) | `ROUNDABOUT_SLIGHT_LEFT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_slight_left_clockwise.png) | `ROUNDABOUT_SLIGHT_LEFT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_left_counterclockwise.png) | `ROUNDABOUT_LEFT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_left_clockwise.png) | `ROUNDABOUT_LEFT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_sharp_left_counterclockwise.png) | `ROUNDABOUT_SHARP_LEFT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_sharp_left_clockwise.png) | `ROUNDABOUT_SHARP_LEFT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_u_turn_counterclockwise.png) | `ROUNDABOUT_U_TURN_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_u_turn_clockwise.png) | `ROUNDABOUT_U_TURN_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_counterclockwise.png) | `ROUNDABOUT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_clockwise.png) | `ROUNDABOUT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_exit_counterclockwise.png) | `ROUNDABOUT_EXIT_COUNTERCLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_roundabout_exit_clockwise.png) | `ROUNDABOUT_EXIT_CLOCKWISE` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_merge_right.png) | `MERGE_RIGHT` `OFF_RAMP_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_merge_left.png) | `MERGE_LEFT` `OFF_RAMP_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_fork_right.png) | `FORK_RIGHT` `TURN_KEEP_RIGHT` `ON_RAMP_KEEP_RIGHT` `OFF_RAMP_KEEP_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_fork_left.png) | `FORK_LEFT` `TURN_KEEP_LEFT` `ON_RAMP_KEEP_LEFT` `OFF_RAMP_KEEP_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_merge.png) | `MERGE_UNSPECIFIED` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_destination.png) | `DESTINATION` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_destination_right.png) | `DESTINATION_RIGHT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_destination_left.png) | `DESTINATION_LEFT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_ferry_boat.png) | `FERRY_BOAT` |
| ![](https://developers.google.com/static/maps/documentation/navigation/images/ic_ferry_train.png) | `FERRY_TRAIN` |

### Use generated icons

![A small list of generated icons provided by the Navigation
SDK.](https://developers.google.com/static/maps/documentation/navigation/android-sdk/images/IconsGenerated.png)

To facilitate Android Auto use cases, the
Navigation SDK supports generation of maneuver and lane
guidance icons. These icons fit the image sizing guidance of the Android Auto
Car App library which recommends targeting a 500 x 74 dp bounding box. See
[setsLaneImage](https://developer.android.com/reference/androidx/car/app/navigation/model/Step.Builder#setLanesImage(androidx.car.app.model.CarIcon))
and
[CarIcon](https://developer.android.com/reference/androidx/car/app/model/CarIcon)
in the Android reference documentation for details.

> [!NOTE]
> **Note:** Icon generation is disabled by default.

#### Icon generation example

    NavigationUpdatesOptions options =
      NavigationUpdatesOptions.builder()
                 .setNumNextStepsToPreview(numNextStepsToPreview)
                 .setGeneratedStepImagesType(GeneratedStepImagesType.BITMAP)
                 .setDisplayMetrics(getResources().getDisplayMetrics())
                 .build();
    boolean isRegistered =
              navigator.registerServiceForNavUpdates(
                  getPackageName(),
                  NavInfoReceivingService.class.getName(),
                  options);

After you enable icon generation, the TurnbyTurn `StepInfo` object populates the
*maneuverBitmap* and *lanesBitmap* fields with the icons.

## What's next

- **For Android Auto apps** :
  - [Draw the map and enable
    navigation](https://developers.google.com/maps/documentation/navigation/android-sdk/android-auto?section=surface-callbacks#draw_the_map_and_navigation_ui).