@jacques_gordon/expo-mapbox-navigation 2.0.5 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -5,20 +5,17 @@ import android.util.Log
|
|
|
5
5
|
import com.mapbox.api.directions.v5.models.RouteOptions
|
|
6
6
|
import com.mapbox.geojson.Point
|
|
7
7
|
import com.mapbox.maps.MapView
|
|
8
|
-
import com.mapbox.maps.MapboxMap
|
|
9
8
|
import com.mapbox.maps.Style
|
|
10
|
-
import com.mapbox.maps.plugin.animation.camera
|
|
11
9
|
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
|
|
12
|
-
import com.mapbox.navigation.base.formatter.UnitType
|
|
13
10
|
import com.mapbox.navigation.base.options.NavigationOptions
|
|
14
11
|
import com.mapbox.navigation.base.route.NavigationRoute
|
|
15
12
|
import com.mapbox.navigation.base.route.NavigationRouterCallback
|
|
16
13
|
import com.mapbox.navigation.base.route.RouterFailure
|
|
14
|
+
import com.mapbox.navigation.base.route.RouterOrigin
|
|
17
15
|
import com.mapbox.navigation.core.MapboxNavigation
|
|
18
16
|
import com.mapbox.navigation.core.MapboxNavigationProvider
|
|
19
17
|
import com.mapbox.navigation.core.directions.session.RoutesObserver
|
|
20
18
|
import com.mapbox.navigation.core.directions.session.RoutesUpdatedResult
|
|
21
|
-
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
|
|
22
19
|
import com.mapbox.navigation.core.trip.session.RouteProgressObserver
|
|
23
20
|
import com.mapbox.navigation.ui.maps.camera.NavigationCamera
|
|
24
21
|
import com.mapbox.navigation.ui.maps.camera.data.MapboxNavigationViewportDataSource
|
|
@@ -36,17 +33,14 @@ private const val TAG = "ExpoMapboxNavigation"
|
|
|
36
33
|
class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
37
34
|
ExpoView(context, appContext) {
|
|
38
35
|
|
|
39
|
-
// ── UI ───────────────────────────────────────────────────────────────────
|
|
40
36
|
private val mapView: MapView = MapView(context)
|
|
41
37
|
private var navigationCamera: NavigationCamera? = null
|
|
42
38
|
private var viewportDataSource: MapboxNavigationViewportDataSource? = null
|
|
43
39
|
private var routeLineApi: MapboxRouteLineApi? = null
|
|
44
40
|
private var routeLineView: MapboxRouteLineView? = null
|
|
45
|
-
|
|
46
|
-
// ── Navigation ───────────────────────────────────────────────────────────
|
|
47
41
|
private var mapboxNavigation: MapboxNavigation? = null
|
|
48
42
|
|
|
49
|
-
//
|
|
43
|
+
// Props
|
|
50
44
|
private var coordinates: List<Map<String, Double>> = emptyList()
|
|
51
45
|
private var waypointIndices: List<Int>? = null
|
|
52
46
|
private var language: String? = null
|
|
@@ -67,51 +61,27 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
67
61
|
setupNavigation()
|
|
68
62
|
}
|
|
69
63
|
|
|
70
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
71
|
-
// Setup
|
|
72
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
73
|
-
|
|
74
64
|
private fun setupNavigation() {
|
|
75
|
-
val
|
|
76
|
-
Log.e(TAG, "Mapbox access token not found.")
|
|
77
|
-
return
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Create MapboxNavigation instance (Nav SDK v3 API)
|
|
81
|
-
val navigationOptions = NavigationOptions.Builder(context)
|
|
82
|
-
.build()
|
|
83
|
-
|
|
65
|
+
val navigationOptions = NavigationOptions.Builder(context).build()
|
|
84
66
|
mapboxNavigation = MapboxNavigationProvider.create(navigationOptions)
|
|
85
67
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
68
|
+
mapView.getMapboxMap().loadStyle(mapStyle ?: Style.MAPBOX_STREETS) { style ->
|
|
69
|
+
routeLineApi = MapboxRouteLineApi(MapboxRouteLineApiOptions.Builder().build())
|
|
70
|
+
routeLineView = MapboxRouteLineView(MapboxRouteLineViewOptions.Builder(context).build())
|
|
71
|
+
|
|
72
|
+
viewportDataSource = MapboxNavigationViewportDataSource(mapView.getMapboxMap())
|
|
73
|
+
navigationCamera = NavigationCamera(
|
|
74
|
+
mapView.getMapboxMap(),
|
|
75
|
+
mapView.camera,
|
|
76
|
+
viewportDataSource!!
|
|
77
|
+
)
|
|
92
78
|
registerObservers()
|
|
93
79
|
}
|
|
94
80
|
}
|
|
95
81
|
|
|
96
|
-
private fun setupRouteLineComponents(style: Style) {
|
|
97
|
-
routeLineApi = MapboxRouteLineApi(MapboxRouteLineApiOptions.Builder().build())
|
|
98
|
-
routeLineView = MapboxRouteLineView(MapboxRouteLineViewOptions.Builder(context).build())
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
private fun setupCamera() {
|
|
102
|
-
val mapboxMap = mapView.getMapboxMap()
|
|
103
|
-
viewportDataSource = MapboxNavigationViewportDataSource(mapboxMap)
|
|
104
|
-
navigationCamera = NavigationCamera(
|
|
105
|
-
mapboxMap,
|
|
106
|
-
mapView.camera,
|
|
107
|
-
viewportDataSource!!
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
82
|
private fun registerObservers() {
|
|
112
83
|
val nav = mapboxNavigation ?: return
|
|
113
84
|
|
|
114
|
-
// Routes observer — updates route line on map
|
|
115
85
|
nav.registerRoutesObserver(object : RoutesObserver {
|
|
116
86
|
override fun onRoutesChanged(result: RoutesUpdatedResult) {
|
|
117
87
|
val routes = result.navigationRoutes
|
|
@@ -121,10 +91,8 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
121
91
|
routeLineView?.renderRouteDrawData(style, value)
|
|
122
92
|
}
|
|
123
93
|
}
|
|
124
|
-
// Issue #43 fix: safe camera transition to following
|
|
125
94
|
safeCameraFollowing()
|
|
126
|
-
|
|
127
|
-
sendEvent("onRoutesReady", mapOf(
|
|
95
|
+
emit("onRoutesReady", mapOf(
|
|
128
96
|
"routeCount" to routes.size,
|
|
129
97
|
"distanceMeters" to (routes.firstOrNull()?.directionsRoute?.distance() ?: 0.0),
|
|
130
98
|
"durationSeconds" to (routes.firstOrNull()?.directionsRoute?.duration() ?: 0.0)
|
|
@@ -133,21 +101,19 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
133
101
|
}
|
|
134
102
|
})
|
|
135
103
|
|
|
136
|
-
// Route progress observer
|
|
137
104
|
nav.registerRouteProgressObserver(RouteProgressObserver { progress ->
|
|
138
|
-
|
|
105
|
+
emit("onRouteProgressChanged", mapOf(
|
|
139
106
|
"distanceRemaining" to progress.distanceRemaining,
|
|
140
107
|
"durationRemaining" to progress.durationRemaining,
|
|
141
108
|
"distanceTraveled" to progress.distanceTraveled,
|
|
142
109
|
"fractionTraveled" to progress.fractionTraveled,
|
|
143
|
-
"currentStepDistanceRemaining" to
|
|
110
|
+
"currentStepDistanceRemaining" to
|
|
111
|
+
(progress.currentLegProgress?.currentStepProgress?.distanceRemaining ?: 0f)
|
|
144
112
|
))
|
|
145
113
|
})
|
|
146
114
|
}
|
|
147
115
|
|
|
148
|
-
//
|
|
149
|
-
// Issue #43 fix: safe camera transition
|
|
150
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
116
|
+
// ── Issue #43: safe camera transition ────────────────────────────────────
|
|
151
117
|
private fun safeCameraFollowing() {
|
|
152
118
|
try {
|
|
153
119
|
navigationCamera?.requestNavigationCameraToFollowing(
|
|
@@ -160,9 +126,7 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
160
126
|
}
|
|
161
127
|
}
|
|
162
128
|
|
|
163
|
-
//
|
|
164
|
-
// Issue #31 fix: voice units
|
|
165
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
129
|
+
// ── Issue #31: voice units ────────────────────────────────────────────────
|
|
166
130
|
private fun resolveUnitType(): String {
|
|
167
131
|
return when (voiceUnits?.lowercase()) {
|
|
168
132
|
"metric" -> "metric"
|
|
@@ -175,9 +139,6 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
175
139
|
}
|
|
176
140
|
}
|
|
177
141
|
|
|
178
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
179
|
-
// Route request
|
|
180
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
181
142
|
private fun fetchRoutes() {
|
|
182
143
|
val nav = mapboxNavigation ?: return
|
|
183
144
|
if (coordinates.size < 2) return
|
|
@@ -187,37 +148,31 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
187
148
|
}
|
|
188
149
|
|
|
189
150
|
val locale = language?.let { Locale.forLanguageTag(it) } ?: Locale.getDefault()
|
|
190
|
-
val unitType = resolveUnitType()
|
|
191
151
|
|
|
192
152
|
val builder = RouteOptions.builder()
|
|
193
153
|
.applyDefaultNavigationOptions()
|
|
194
154
|
.language(locale.toLanguageTag())
|
|
195
|
-
.voiceUnits(
|
|
155
|
+
.voiceUnits(resolveUnitType())
|
|
196
156
|
.coordinatesList(points)
|
|
197
157
|
|
|
198
158
|
waypointIndices?.let { builder.waypointIndicesList(it) }
|
|
199
|
-
|
|
200
159
|
navigationProfile?.let {
|
|
201
|
-
|
|
202
|
-
builder.profile(profile)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
excludeTypes?.takeIf { it.isNotEmpty() }?.let {
|
|
206
|
-
builder.exclude(it.joinToString(","))
|
|
160
|
+
builder.profile(if (it.startsWith("mapbox/")) it else "mapbox/$it")
|
|
207
161
|
}
|
|
208
|
-
|
|
162
|
+
excludeTypes?.takeIf { it.isNotEmpty() }?.let { builder.exclude(it.joinToString(",")) }
|
|
209
163
|
maxHeight?.let { builder.maxHeight(it) }
|
|
210
164
|
maxWidth?.let { builder.maxWidth(it) }
|
|
211
165
|
|
|
166
|
+
// Nav SDK v3: NavigationRouterCallback uses @RouterOrigin String (not enum)
|
|
212
167
|
nav.requestRoutes(
|
|
213
168
|
builder.build(),
|
|
214
169
|
object : NavigationRouterCallback {
|
|
215
170
|
override fun onRoutesReady(
|
|
216
171
|
routes: List<NavigationRoute>,
|
|
217
|
-
routerOrigin:
|
|
172
|
+
@RouterOrigin routerOrigin: String
|
|
218
173
|
) {
|
|
219
174
|
if (routes.isEmpty()) {
|
|
220
|
-
|
|
175
|
+
emit("onRoutesFailed", mapOf("message" to "No routes returned"))
|
|
221
176
|
return
|
|
222
177
|
}
|
|
223
178
|
nav.setNavigationRoutes(routes)
|
|
@@ -230,12 +185,12 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
230
185
|
) {
|
|
231
186
|
val msg = reasons.firstOrNull()?.message ?: "Unknown error"
|
|
232
187
|
Log.e(TAG, "Route request failed: $msg")
|
|
233
|
-
|
|
188
|
+
emit("onRoutesFailed", mapOf("message" to msg))
|
|
234
189
|
}
|
|
235
190
|
|
|
236
191
|
override fun onCanceled(
|
|
237
192
|
routeOptions: RouteOptions,
|
|
238
|
-
routerOrigin:
|
|
193
|
+
@RouterOrigin routerOrigin: String
|
|
239
194
|
) {
|
|
240
195
|
Log.d(TAG, "Route request cancelled")
|
|
241
196
|
}
|
|
@@ -243,15 +198,11 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
243
198
|
)
|
|
244
199
|
}
|
|
245
200
|
|
|
246
|
-
//
|
|
247
|
-
// Prop setters
|
|
248
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
249
|
-
|
|
201
|
+
// ── Prop setters ──────────────────────────────────────────────────────────
|
|
250
202
|
fun setCoordinates(coords: List<Map<String, Double>>) {
|
|
251
203
|
coordinates = coords
|
|
252
204
|
if (coords.size >= 2) fetchRoutes()
|
|
253
205
|
}
|
|
254
|
-
|
|
255
206
|
fun setWaypointIndices(indices: List<Int>?) { waypointIndices = indices }
|
|
256
207
|
fun setLanguage(lang: String?) { language = lang }
|
|
257
208
|
fun setVoiceUnits(units: String?) { voiceUnits = units }
|
|
@@ -265,10 +216,7 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
265
216
|
fun setCustomRasterTileUrl(url: String?) { customRasterTileUrl = url }
|
|
266
217
|
fun setCustomRasterAboveLayerId(layerId: String?) { customRasterAboveLayerId = layerId }
|
|
267
218
|
|
|
268
|
-
//
|
|
269
|
-
// Helpers
|
|
270
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
271
|
-
|
|
219
|
+
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
272
220
|
private fun getAccessToken(): String? {
|
|
273
221
|
return try {
|
|
274
222
|
val resId = context.resources.getIdentifier(
|
|
@@ -278,8 +226,13 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
278
226
|
} catch (e: Exception) { null }
|
|
279
227
|
}
|
|
280
228
|
|
|
281
|
-
|
|
282
|
-
|
|
229
|
+
// Correct Expo SDK v53 event emitter API
|
|
230
|
+
private fun emit(name: String, data: Map<String, Any>) {
|
|
231
|
+
try {
|
|
232
|
+
appContext.eventEmitter?.emit(name, data)
|
|
233
|
+
} catch (e: Exception) {
|
|
234
|
+
Log.e(TAG, "Failed to emit event $name: ${e.message}")
|
|
235
|
+
}
|
|
283
236
|
}
|
|
284
237
|
|
|
285
238
|
override fun onDetachedFromWindow() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jacques_gordon/expo-mapbox-navigation",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"description": "Expo module for Mapbox Navigation SDK with 16KB page size support, NDK27, and Mapbox Maps v11.11.0+",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|