Skip to content

Commit 0658b0d

Browse files
Address PR #12 review feedback
Fixed 8 issues identified in review: 1. Optimization API bug: Removed numeric index fallback, only use 'first'/'any' for source and 'last'/'any' for destination 2. Added missing async keyword to getCachedRoute function in AGENTS.md 3. Added missing 'unknown' congestion value to traffic styling match expression 4. Fixed API Limits table: Changed "Up to 3" to "Max 2 alternatives (3 total routes)", clarified Optimization v1 hard limit 5. Fixed skills README alphabetical ordering: moved mapbox-navigation-patterns between maplibre-migration and search-integration 6. Updated iOS Navigation SDK to v3 API: - Changed imports: MapboxNavigation → MapboxNavigationUIKit, MapboxCoreNavigation → MapboxNavigationCore - Replaced Directions.shared.calculate() callbacks with async/await routingProvider.calculateRoutes() - Updated NavigationViewController initialization with navigationRoutes and navigationOptions - Replaced MapboxNavigationService with MapboxNavigationProvider - Converted NavigationServiceDelegate callbacks to Combine publishers - Updated voice guidance configuration to use CoreConfig.ttsConfig 7. Updated Android Navigation SDK to v3 API: - Removed NavigationView examples (dropped in v3) - Removed api.startArrival() method (not documented) - Removed .accessToken() method (removed in v3) - Changed onDestroy() to use MapboxNavigationProvider.destroy() - Updated to v3-compatible patterns with requestRoutes() and RouteProgressObserver 8. All code examples now use current v3 SDK APIs for both iOS and Android Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent d4ddc13 commit 0658b0d

3 files changed

Lines changed: 382 additions & 221 deletions

File tree

skills/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This directory contains [Agent Skills](https://agentskills.io) that provide doma
99
| [mapbox-geospatial-operations](./mapbox-geospatial-operations/) | Choosing between offline geometric tools and routing APIs for geospatial operations |
1010
| [mapbox-google-maps-migration](./mapbox-google-maps-migration/) | Migration guide from Google Maps Platform to Mapbox GL JS with API equivalents and patterns |
1111
| [mapbox-maplibre-migration](./mapbox-maplibre-migration/) | Migration guide between Mapbox GL JS and MapLibre GL JS in both directions |
12+
| [mapbox-navigation-patterns](./mapbox-navigation-patterns/) | Navigation and routing patterns for Directions API and Navigation SDKs |
1213
| [mapbox-search-integration](./mapbox-search-integration/) | Complete workflow for implementing Mapbox search with discovery questions and best practices |
1314
| [mapbox-search-patterns](./mapbox-search-patterns/) | Choosing the right search tool and parameters for geocoding and POI search |
1415
| [mapbox-web-performance-patterns](./mapbox-web-performance-patterns/) | Performance optimization for Mapbox GL JS (initialization, markers, data loading, memory) |
@@ -19,7 +20,6 @@ This directory contains [Agent Skills](https://agentskills.io) that provide doma
1920
| [mapbox-style-patterns](./mapbox-style-patterns/) | Common style patterns and layer configurations |
2021
| [mapbox-style-quality](./mapbox-style-quality/) | Style validation, accessibility, optimization |
2122
| [mapbox-token-security](./mapbox-token-security/) | Security best practices for access tokens |
22-
| [mapbox-navigation-patterns](./mapbox-navigation-patterns/) | Navigation and routing patterns for Directions API and Navigation SDKs |
2323
| [mapbox-store-locator-patterns](./mapbox-store-locator-patterns/) | Store locator and location finder patterns with markers, filtering, and distance calculation |
2424

2525
## Documentation

skills/mapbox-navigation-patterns/AGENTS.md

Lines changed: 142 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -105,30 +105,44 @@ steps.forEach((step) => {
105105
### Basic Navigation
106106

107107
```swift
108-
import MapboxNavigation
109-
110-
// Define waypoints
111-
let origin = Waypoint(coordinate: start, name: "Start")
112-
let destination = Waypoint(coordinate: end, name: "End")
108+
import MapboxNavigationCore
109+
import MapboxNavigationUIKit
110+
111+
// Initialize provider
112+
let mapboxNavigationProvider = MapboxNavigationProvider(
113+
coreConfig: CoreConfig(
114+
locationSource: .live,
115+
ttsConfig: .default // Voice guidance enabled
116+
)
117+
)
113118

114-
// Request route
115-
let options = NavigationRouteOptions(waypoints: [origin, destination])
119+
// Calculate routes with async/await
120+
Task {
121+
do {
122+
let options = NavigationRouteOptions(
123+
coordinates: [start, end]
124+
)
116125

117-
Directions.shared.calculate(options) { (_, result) in
118-
switch result {
119-
case .success(let response):
120-
let route = response.routes!.first!
126+
let navigationRoutes = try await mapboxNavigationProvider
127+
.mapboxNavigation
128+
.routingProvider()
129+
.calculateRoutes(options: options)
130+
.value
121131

122132
// Show full navigation UI
133+
let navigationOptions = NavigationOptions(
134+
mapboxNavigation: mapboxNavigationProvider.mapboxNavigation,
135+
voiceController: mapboxNavigationProvider.routeVoiceController,
136+
eventsManager: mapboxNavigationProvider.eventsManager()
137+
)
138+
123139
let navVC = NavigationViewController(
124-
for: route,
125-
routeIndex: 0,
126-
routeOptions: options
140+
navigationRoutes: navigationRoutes,
141+
navigationOptions: navigationOptions
127142
)
128-
navVC.delegate = self
129143
present(navVC, animated: true)
130144

131-
case .failure(let error):
145+
} catch {
132146
print("Error: \(error)")
133147
}
134148
}
@@ -137,91 +151,145 @@ Directions.shared.calculate(options) { (_, result) in
137151
### Custom Navigation UI
138152

139153
```swift
140-
import MapboxCoreNavigation
154+
import MapboxNavigationCore
155+
import Combine
141156

142-
// Core navigation without UI
143-
let service = MapboxNavigationService(
144-
routeResponse: response,
145-
routeIndex: 0,
146-
routeOptions: options
147-
)
157+
class CustomNavigation {
158+
private let provider: MapboxNavigationProvider
159+
private var subscriptions = Set<AnyCancellable>()
148160

149-
service.delegate = self
150-
service.start()
151-
152-
// Implement NavigationServiceDelegate
153-
func navigationService(_ service: NavigationService,
154-
didUpdate progress: RouteProgress,
155-
with location: CLLocation,
156-
rawLocation: CLLocation) {
157-
// Update your custom UI
158-
let instruction = progress.currentLegProgress.currentStepProgress.step.instructions
159-
let distance = progress.currentLegProgress.currentStepProgress.distanceRemaining
161+
init() {
162+
provider = MapboxNavigationProvider(coreConfig: CoreConfig())
163+
setupSubscriptions()
164+
}
165+
166+
func setupSubscriptions() {
167+
let navigation = provider.mapboxNavigation.navigation()
168+
169+
// Subscribe to route progress
170+
navigation.routeProgress
171+
.sink { [weak self] progressState in
172+
guard let progress = progressState?.routeProgress else { return }
173+
self?.updateUI(progress)
174+
}
175+
.store(in: &subscriptions)
176+
177+
// Subscribe to banner instructions
178+
navigation.bannerInstructions
179+
.removeDuplicates()
180+
.sink { [weak self] state in
181+
guard let instruction = state.visualInstruction else { return }
182+
self?.showInstruction(instruction.primaryInstruction.text)
183+
}
184+
.store(in: &subscriptions)
185+
}
186+
187+
func updateUI(_ progress: RouteProgress) {
188+
let distance = progress.currentLegProgress?.currentStepProgress.distanceRemaining
189+
// Update your custom UI
190+
}
191+
192+
func showInstruction(_ text: String) {
193+
// Display instruction in custom UI
194+
}
160195
}
161196
```
162197

163198
### Voice Guidance
164199

165200
```swift
166-
let voiceController = navigationService.voiceController
167-
168-
// Configure language
169-
voiceController.locale = Locale(identifier: "en-US")
201+
// Configure voice via CoreConfig when creating provider
202+
let provider = MapboxNavigationProvider(
203+
coreConfig: CoreConfig(
204+
ttsConfig: .default // or .localOnly, .custom(synthesizer)
205+
)
206+
)
170207

171-
// Control volume
172-
voiceController.volume = .normal // or .muted, .custom(0.5)
208+
// Set language via route options
209+
var options = NavigationRouteOptions(coordinates: [start, end])
210+
options.locale = Locale(identifier: "es-ES") // Spanish
211+
options.distanceMeasurementSystem = .metric
173212
```
174213

175214
## Navigation SDK for Android
176215

177216
### Basic Navigation
178217

179218
```kotlin
180-
import com.mapbox.navigation.dropin.NavigationView
181-
182-
// NavigationView provides complete UI
183-
val navigationView = findViewById<NavigationView>(R.id.navigationView)
219+
import com.mapbox.navigation.core.MapboxNavigationProvider
220+
import com.mapbox.navigation.base.options.NavigationOptions
221+
import com.mapbox.navigation.base.route.NavigationRouterCallback
222+
import com.mapbox.geojson.Point
184223

185-
navigationView.api.startArrival(
186-
Waypoint.builder()
187-
.coordinate(Point.fromLngLat(lng, lat))
188-
.name("Destination")
189-
.build()
190-
)
191-
```
192-
193-
### Custom Navigation UI
194-
195-
```kotlin
196-
import com.mapbox.navigation.core.MapboxNavigation
197-
198-
// Core navigation
224+
// Initialize MapboxNavigation
199225
val mapboxNavigation = MapboxNavigationProvider.create(
200-
NavigationOptions.Builder(context)
201-
.accessToken(token)
202-
.build()
226+
NavigationOptions.Builder(context).build()
203227
)
204228

205229
// Request route
206230
val routeOptions = RouteOptions.builder()
207231
.applyDefaultNavigationOptions()
208-
.coordinatesList(listOf(origin, destination))
232+
.coordinatesList(listOf(
233+
Point.fromLngLat(originLng, originLat),
234+
Point.fromLngLat(destLng, destLat)
235+
))
209236
.build()
210237

211-
mapboxNavigation.requestRoutes(routeOptions, callback)
238+
mapboxNavigation.requestRoutes(
239+
routeOptions,
240+
object : NavigationRouterCallback {
241+
override fun onRoutesReady(
242+
routes: List<NavigationRoute>,
243+
routerOrigin: String
244+
) {
245+
mapboxNavigation.setNavigationRoutes(routes)
246+
mapboxNavigation.startTripSession()
247+
}
248+
249+
override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
250+
// Handle failure
251+
}
252+
253+
override fun onCanceled(routeOptions: RouteOptions, routerOrigin: String) {
254+
// Handle cancellation
255+
}
256+
}
257+
)
258+
259+
// Cleanup
260+
override fun onDestroy() {
261+
super.onDestroy()
262+
MapboxNavigationProvider.destroy()
263+
}
264+
```
265+
266+
### Custom Navigation UI
267+
268+
```kotlin
269+
import com.mapbox.navigation.core.trip.session.RouteProgressObserver
212270

213-
// Start navigation
214-
mapboxNavigation.registerRouteProgressObserver { routeProgress ->
215-
// Update UI
271+
// Register route progress observer
272+
private val routeProgressObserver = RouteProgressObserver { routeProgress ->
273+
// Update custom UI
216274
val instruction = routeProgress.currentLegProgress
217275
?.currentStepProgress?.step
218276
?.bannerInstructions?.firstOrNull()?.primary?.text
219277

220278
val distanceRemaining = routeProgress.currentLegProgress
221279
?.currentStepProgress?.distanceRemaining
280+
281+
val durationRemaining = routeProgress.durationRemaining
282+
}
283+
284+
override fun onStart() {
285+
super.onStart()
286+
mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
222287
}
223288

224-
mapboxNavigation.startTripSession()
289+
override fun onStop() {
290+
super.onStop()
291+
mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
292+
}
225293
```
226294

227295
## Routing Profiles
@@ -240,7 +308,7 @@ mapboxNavigation.startTripSession()
240308
```javascript
241309
const cache = new Map();
242310

243-
function getCachedRoute(start, end) {
311+
async function getCachedRoute(start, end) {
244312
const key = `${start}-${end}`;
245313
const cached = cache.get(key);
246314

@@ -324,12 +392,12 @@ const url = `https://api.mapbox.com/directions/v5/mapbox/cycling/${coords}?...`;
324392

325393
## API Limits
326394

327-
| Feature | Limit |
328-
| ---------------------- | -------------------------------------- |
329-
| **Waypoints** | 25 max (including start/end) |
330-
| **Alternative routes** | Up to 3 |
331-
| **Optimization** | 12 waypoints (free tier), 25 (premium) |
332-
| **Rate limit** | 300 requests/minute (default) |
395+
| Feature | Limit |
396+
| ---------------------- | --------------------------------------------- |
397+
| **Waypoints** | 25 max (including start/end) |
398+
| **Alternative routes** | Max 2 alternatives (3 total routes) |
399+
| **Optimization** | 12 waypoints (v1 API hard limit) |
400+
| **Rate limit** | 300 requests/minute (default) |
333401

334402
## Quick Decisions
335403

0 commit comments

Comments
 (0)