Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions docs/navigation/free-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
id: free-drive
sidebar_position: 6
title: "Free drive: road name and speed limit without a route"
sidebar_label: Free drive
description: "Track the device on the road network without a route with @rnmapbox/navigation: road name, speed limit, the navigation puck and the session state."
---

Outside guidance the navigation session is idle: no location events and no puck on navigation maps. `Navigation.startFreeDrive()` matches the device's location to the road network without a route, so `addLocationListener` reports the road name and speed limit, and navigation maps show the puck. `Navigation.stopNavigation()` ends it.

```tsx
import { useEffect, useState } from 'react';
import Navigation, { type LocationEvent } from '@rnmapbox/navigation';

export function useFreeDrive() {
const [location, setLocation] = useState<LocationEvent>();

useEffect(() => {
const subscription = Navigation.addLocationListener(setLocation);
Navigation.startFreeDrive().catch((error) => {
// error.code === 'location_permission': ask for the permission first
console.warn(error);
});
return () => {
subscription.remove();
Navigation.stopNavigation();
};
}, []);

return location; // location?.roadName, location?.speedLimit?.speed, location?.speedLimit?.unit
}
```

- Mapbox bills free drive trips like guidance trips, see [Navigation SDK pricing](https://www.mapbox.com/pricing#navigation). Nothing in this package starts free drive on its own, CarPlay included. It runs from `startFreeDrive` until `stopNavigation` or a JS reload.
- Without location permission, `startFreeDrive` rejects with `code: 'location_permission'`, see [Location permission](install.md#location-permission).
- During guidance, `startFreeDrive()` ends the guidance and keeps the session in free drive.
- `<NavigationView>` and `<RNNavigationView>` started from free drive return to it when they unmount or the user ends the trip.

`speedLimit` is missing where the road has no known limit. Its `sign` is `'mutcd'` (US-style rectangle) or `'vienna'` (red circle), see [`LocationEvent`](api/Events/LocationEvent.md).

## Simulated location

`startFreeDrive({ simulatedLocation: [longitude, latitude] })` parks a simulated device at that position instead of using the device's location, and needs no location permission. After simulated guidance, `startFreeDrive()` keeps the simulated device where guidance stopped.

## Android background tracking

On Android, free drive runs without the Navigation SDK's foreground service, so Android throttles its location updates while the app is in the background. `startFreeDrive({ foregroundService: true })` keeps tracking in the background with the SDK's notification, which also keeps the billed trip going while the app isn't visible, until `stopNavigation`. Live guidance always uses the foreground service. iOS and simulated free drive ignore the option.

## Session state

`Navigation.getSessionState()` returns `'idle'`, `'freeDrive'` or `'activeGuidance'`, and `addSessionStateListener` reports changes, whether they come from JS, `<NavigationView>` or the car screen.

```tsx
const [sessionState, setSessionState] = useState(Navigation.getSessionState);

useEffect(() => {
const subscription = Navigation.addSessionStateListener(setSessionState);
return () => subscription.remove();
}, []);
```

On iOS they follow the SDK's session; on Android they follow this package's calls.
12 changes: 10 additions & 2 deletions docs/navigation/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ useEffect(() => {
| `addVoiceInstructionListener` | `{ text, ssml, distanceAlongStep }`, for apps doing their own text to speech. |
| `addCameraStateListener` | Camera state changes, see [Camera](#camera). |

The SDK speaks voice instructions during any guidance; `Navigation.setVoiceMuted(true)` mutes them. See the [API reference](api/index.md) for the event types.
The SDK speaks voice instructions during any guidance; `Navigation.setVoiceMuted(true)` mutes them, see [Guidance controls](guidance-controls.md#voice). See the [API reference](api/index.md) for the event types.

## Routes

`requestRoutes` resolves to `{ main, alternatives }`. A `Route` is backed by the native SDK route and holds native memory:
`requestRoutes` resolves to `{ main, alternatives }`; see [Route options](route-options.md) for what it takes, and [Map Matching](map-matching.md) for routes along your own path. A `Route` is backed by the native SDK route and holds native memory:

- Its getters (`distance`, `expectedTravelTime`, `geometry`, `legs`) read a copy taken when the route was created. They're synchronous.
- `release()` frees the native route. Release the routes you don't keep, such as unused alternatives. The garbage collector releases the rest eventually, but it doesn't see the native memory, so that can take long.
Expand Down Expand Up @@ -150,3 +150,11 @@ The state switches to `idle` when a pan, pinch, rotate, pitch or double-tap gest
- `Camera` `followUserLocation` and the navigation camera both drive the map. Don't combine them.

After `stopNavigation`, the route and the puck are removed and the camera eases back to north-up, without tilt or padding.

## Next steps

- [Route options](route-options.md): waypoints, roads and points to avoid, vehicle limits, departure time.
- [Map Matching](map-matching.md): guide along a path you define.
- [Free drive](free-drive.md): road name and speed limit without a route, and the session state.
- [Guidance controls](guidance-controls.md): multi-stop routes, simulation speed, voice and keeping the screen on.
- [Styling](styling.md): route line colors and day and night map styles.
71 changes: 71 additions & 0 deletions docs/navigation/guidance-controls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
id: guidance-controls
sidebar_position: 7
title: "Guidance controls: stops, simulation speed, voice and screen"
sidebar_label: Guidance controls
description: "Control a running @rnmapbox/navigation guidance session: advance between stops, simulation speed, voice volume and mute, and keeping the screen on."
---

These settings apply to the app's single navigation session, so they also affect `<NavigationView>` and `<RNNavigationView>`.

## Multi-stop routes

Each non-silent waypoint after the origin ends a leg, see [Waypoints](route-options.md#waypoints). When guidance arrives at one, `addArriveListener` reports `{ waypointIndex, isFinalDestination }` and guidance moves on to the next leg by itself.

To wait at each stop, e.g. until a delivery is confirmed, turn that off and advance yourself:

```tsx
import { Alert } from 'react-native';
import Navigation from '@rnmapbox/navigation';

Navigation.setAutoAdvanceLegs(false);

const subscription = Navigation.addArriveListener(({ isFinalDestination }) => {
if (!isFinalDestination) {
Alert.alert('Delivered?', undefined, [
{ text: 'Next stop', onPress: () => Navigation.advanceToNextLeg() },
]);
}
});
```

- With auto-advance off, guidance stays at the waypoint until `advanceToNextLeg()`, simulated guidance included. Turning it back on while guidance waits doesn't move on; call `advanceToNextLeg()`.
- `advanceToNextLeg()` also skips a stop. Away from the waypoint, guidance reroutes from where it is; simulated guidance jumps to the start of the next leg and reroutes again.
- It does nothing on the last leg or without active guidance.

## Simulation speed

`Navigation.setSimulationSpeed(multiplier)` drives simulated guidance faster or slower than the route's expected speeds, e.g. `2` for twice as fast. The default is `1`. It applies to the running simulation and later ones, and throws unless `multiplier` is positive.

```tsx
Navigation.setSimulationSpeed(2);
await Navigation.startActiveGuidance(route, { simulate: true });
```

- Simulated locations keep reporting the route's speed, not multiplied.
- Higher speeds can make guidance go off route at sharp turns and reroute. This was seen at U-turns from 4× on Android and at 8× on iOS.
- On Android the simulation doesn't follow reroutes, so after one it can stop short of the destination.

## Voice

The SDK speaks voice instructions during any guidance.

| Function | Description |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `setVoiceMuted(muted)` | Mutes or unmutes them. `<NavigationView>`'s mute button toggles the same setting. |
| `isVoiceMuted()` | Whether they're muted, by `setVoiceMuted` or the mute button. |
| `setVoiceVolume(volume)` | Volume from 0 to 1, relative to the device's media volume, clamped to that range. Independent of mute. Throws for `NaN`. |

On iOS the volume doesn't apply to instructions spoken by the system voice, which the SDK falls back to when the Mapbox voice is unavailable, e.g. offline.

For your own text to speech, mute the SDK and subscribe to `addVoiceInstructionListener`, which is called whether or not the SDK speaks.

## Keep screen on

Active guidance, `<NavigationView>`'s included, keeps the screen on. When guidance stops, the app's own idle timer (iOS) or keep screen on (Android) setting is restored. If the app manages that itself, turn it off:

```tsx
Navigation.setKeepScreenOn(false);
```

See [`Navigation`](api/Core/Navigation.md) in the API reference.
2 changes: 1 addition & 1 deletion docs/navigation/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: "Install @rnmapbox/navigation for turn-by-turn navigation in React
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Set up `@rnmapbox/maps` first, following its [install guide](../install.md). `@rnmapbox/navigation` 0.1.0 needs `@rnmapbox/maps` `>=10.3.16 <10.4.0` and React Native 0.79+ with the New Architecture.
Set up `@rnmapbox/maps` first, following its [install guide](../install.md). `@rnmapbox/navigation` needs `@rnmapbox/maps` `>=10.3.16 <10.4.0` and React Native 0.79+ with the New Architecture. See [Versions](overview.md#versions) for older releases.

## Install

Expand Down
51 changes: 51 additions & 0 deletions docs/navigation/map-matching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
id: map-matching
sidebar_position: 5
title: "Guide along your own path with Map Matching"
sidebar_label: Map Matching
description: "Turn a list of coordinates, such as a tour or a delivery run, into a navigable route with the Mapbox Map Matching API and @rnmapbox/navigation."
---

`Navigation.requestMatchedRoutes` snaps a path the app defines, such as a tour or a delivery run, to roads with the [Mapbox Map Matching API](https://docs.mapbox.com/api/navigation/map-matching/), and resolves with a route along it. Use it when the route has to follow your path, rather than the fastest route between the waypoints that `requestRoutes` returns.

```tsx
import Navigation, { type Position } from '@rnmapbox/navigation';

const TOUR: Position[] = [
[-122.39726, 37.79205],
[-122.39612, 37.79310],
[-122.39480, 37.79420],
[-122.39351, 37.79554],
];

const { main } = await Navigation.requestMatchedRoutes({
coordinates: TOUR,
waypointIndices: [0, 2, TOUR.length - 1],
});
await Navigation.startActiveGuidance(main, { simulate: true });
```

The route works with `previewRoute` and `startActiveGuidance` like one from `requestRoutes`, and holds native memory the same way: `release()` it when you're done. `alternatives` is always empty.

## Options

| Option | Description |
| ----------------- | ----------------------------------------------------------------------------------------------- |
| `coordinates` | The path, 2 to 100 positions in order. Each is snapped to the nearest road within its radius, so a sparse trace works. |
| `profile` | `'driving-traffic'` (default), `'driving'`, `'walking'` or `'cycling'`. |
| `waypointIndices` | Indices of the `coordinates` that are waypoints: the route is split into legs there, and guidance announces the arrival. Ascending, including the first and last index. Defaults to the first and last coordinate. |
| `radiuses` | Meters each coordinate may be away from the road, one per coordinate, 0 to 50. The API defaults to 5. |
| `language` | Language of the instructions, e.g. `en` or `de-DE`. |
| `units` | `'metric'` or `'imperial'`, for the distances in voice instructions. |

It rejects without sending a request if the options break these limits, and with `code: 'no_single_match'` if the API can only match the coordinates as several disconnected pieces, e.g. across a gap with no road. Add coordinates in the gap, or raise `radiuses` there.

## Off route

Neither SDK reroutes a matched route, whatever `setRerouteEnabled` says. When the user leaves it, `addOffRouteListener` reports `true` and guidance waits for them to return to the route.

## Platform notes

On Android this uses the SDK's `requestMapMatching`, which the Navigation SDK marks as experimental, so its behavior may change in minor releases.

See [`MatchedRouteRequestOptions`](api/Routes/MatchedRouteRequestOptions.md) in the API reference.
6 changes: 4 additions & 2 deletions docs/navigation/navigation-view.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
id: navigation-view
sidebar_position: 4
sidebar_position: 9
title: "NavigationView: drop-in turn-by-turn navigation UI"
sidebar_label: NavigationView
description: "The Mapbox Navigation SDK's full-screen turn-by-turn UI for React Native on iOS and Android, with maneuver banner, lanes, speed limit and trip progress."
Expand Down Expand Up @@ -38,6 +38,8 @@ See [`NavigationViewProps`](api/Components/NavigationViewProps.md) in the API re
| `waypoints` | `Waypoint[]` | Used without `route`: the view requests a route through them, origin first, and releases it on unmount. |
| `simulate` | `boolean` | Drives the route with simulated locations. Read when guidance starts. Defaults to `false`. |
| `mute` | `boolean` | Mutes voice instructions. The view's own mute button also toggles them. Defaults to `false`. |
| `styleURL` | `string` | Map style by day. Defaults to Mapbox Standard. See [Styling](styling.md#map-styles). |
| `nightStyleURL` | `string` | Map style while the system is in dark mode. Defaults to `styleURL`, or without it to Standard's night preset. |
| `style` | `StyleProp<ViewStyle>` | |
| `testID` | `string` | |
| `onRouteProgress` | `(event: RouteProgressEvent) => void` | Same event as `addRouteProgressListener`. |
Expand All @@ -54,4 +56,4 @@ See [`NavigationViewProps`](api/Components/NavigationViewProps.md) in the API re
- `addRouteProgressListener` and `addCameraStateListener` also report its guidance.
- Show one `NavigationView` at a time. On iOS it's embedded as a child of the nearest view controller.

Android `<NavigationView>` has no end-of-route or feedback UI, no day/night styles, no road name label, and doesn't show reroutes as such. For the same UI on both platforms, see [`<RNNavigationView>`](rn-navigation-view.md).
Android `<NavigationView>` has no end-of-route or feedback UI, no night colors for its UI (only the map switches), no road name label, and doesn't show reroutes as such. For the same UI on both platforms, see [`<RNNavigationView>`](rn-navigation-view.md).
Loading
Loading