Skip to content

Commit 08b55d3

Browse files
Adasis example activity
1 parent b2301f6 commit 08b55d3

File tree

6 files changed

+365
-11
lines changed

6 files changed

+365
-11
lines changed

examples/src/main/AndroidManifest.xml

+6
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@
9595
android:label="@string/title_multileg_route">
9696
</activity>
9797

98+
<activity
99+
android:name=".AdasisActivity"
100+
android:label="@string/title_adasis"
101+
android:screenOrientation="portrait">
102+
</activity>
103+
98104
<activity
99105
android:name="com.mapbox.navigation.examples.MainActivity"
100106
android:exported="true">

examples/src/main/java/com/mapbox/navigation/examples/MainActivity.kt

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
1313
import com.mapbox.android.core.permissions.PermissionsListener
1414
import com.mapbox.common.LogConfiguration
1515
import com.mapbox.common.LoggingLevel
16+
import com.mapbox.navigation.examples.core.AdasisActivity
1617
import com.mapbox.navigation.examples.core.IndependentRouteGenerationActivity
1718
import com.mapbox.navigation.examples.core.MapboxBuildingHighlightActivity
1819
import com.mapbox.navigation.examples.core.MapboxCustomStyleActivity
@@ -143,6 +144,11 @@ class MainActivity : AppCompatActivity(), PermissionsListener {
143144
getString(R.string.description_draw_utility),
144145
RouteDrawingActivity::class.java
145146
),
147+
SampleItem(
148+
getString(R.string.title_adasis),
149+
getString(R.string.description_adasis),
150+
AdasisActivity::class.java
151+
)
146152
)
147153
}
148154

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
package com.mapbox.navigation.examples.core
2+
3+
import android.annotation.SuppressLint
4+
import android.location.Location
5+
import android.os.Bundle
6+
import android.util.Log
7+
import android.view.View
8+
import androidx.appcompat.app.AppCompatActivity
9+
import com.mapbox.api.directions.v5.models.DirectionsRoute
10+
import com.mapbox.api.directions.v5.models.RouteOptions
11+
import com.mapbox.geojson.Point
12+
import com.mapbox.maps.CameraOptions
13+
import com.mapbox.maps.EdgeInsets
14+
import com.mapbox.maps.MapboxMap
15+
import com.mapbox.maps.Style
16+
import com.mapbox.maps.plugin.animation.CameraAnimationsPlugin
17+
import com.mapbox.maps.plugin.animation.MapAnimationOptions
18+
import com.mapbox.maps.plugin.animation.camera
19+
import com.mapbox.maps.plugin.gestures.gestures
20+
import com.mapbox.maps.plugin.locationcomponent.LocationComponentPlugin
21+
import com.mapbox.maps.plugin.locationcomponent.location
22+
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
23+
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
24+
import com.mapbox.navigation.base.extensions.applyLanguageAndVoiceUnitOptions
25+
import com.mapbox.navigation.base.options.NavigationOptions
26+
import com.mapbox.navigation.base.route.NavigationRoute
27+
import com.mapbox.navigation.base.route.NavigationRouterCallback
28+
import com.mapbox.navigation.base.route.RouterFailure
29+
import com.mapbox.navigation.base.route.RouterOrigin
30+
import com.mapbox.navigation.core.MapboxNavigation
31+
import com.mapbox.navigation.core.MapboxNavigationProvider
32+
import com.mapbox.navigation.core.adasis.AdasisConfig
33+
import com.mapbox.navigation.core.directions.session.RoutesObserver
34+
import com.mapbox.navigation.core.replay.MapboxReplayer
35+
import com.mapbox.navigation.core.replay.ReplayLocationEngine
36+
import com.mapbox.navigation.core.replay.route.ReplayProgressObserver
37+
import com.mapbox.navigation.core.replay.route.ReplayRouteMapper
38+
import com.mapbox.navigation.core.trip.session.LocationMatcherResult
39+
import com.mapbox.navigation.core.trip.session.LocationObserver
40+
import com.mapbox.navigation.core.trip.session.RouteProgressObserver
41+
import com.mapbox.navigation.examples.core.databinding.LayoutActivityAdasisBinding
42+
import com.mapbox.navigation.examples.core.waypoints.WaypointsController
43+
import com.mapbox.navigation.ui.maps.location.NavigationLocationProvider
44+
import com.mapbox.navigation.ui.maps.route.arrow.api.MapboxRouteArrowApi
45+
import com.mapbox.navigation.ui.maps.route.arrow.api.MapboxRouteArrowView
46+
import com.mapbox.navigation.ui.maps.route.arrow.model.RouteArrowOptions
47+
import com.mapbox.navigation.ui.maps.route.line.MapboxRouteLineApiExtensions.setNavigationRoutes
48+
import com.mapbox.navigation.ui.maps.route.line.api.MapboxRouteLineApi
49+
import com.mapbox.navigation.ui.maps.route.line.api.MapboxRouteLineView
50+
import com.mapbox.navigation.ui.maps.route.line.model.MapboxRouteLineOptions
51+
import com.mapbox.navigation.ui.maps.route.line.model.RouteLineResources
52+
import kotlinx.coroutines.CoroutineScope
53+
import kotlinx.coroutines.Dispatchers
54+
import kotlinx.coroutines.launch
55+
56+
class AdasisActivity : AppCompatActivity() {
57+
58+
private lateinit var mapboxMap: MapboxMap
59+
private lateinit var mapCamera: CameraAnimationsPlugin
60+
private lateinit var mapboxNavigation: MapboxNavigation
61+
private lateinit var binding: LayoutActivityAdasisBinding
62+
private lateinit var locationComponent: LocationComponentPlugin
63+
private var isNavigating = false
64+
65+
private val mapboxReplayer = MapboxReplayer()
66+
private val navigationLocationProvider = NavigationLocationProvider()
67+
private val waypointsController = WaypointsController()
68+
69+
private val routeLineResources: RouteLineResources by lazy {
70+
RouteLineResources.Builder().build()
71+
}
72+
73+
private val options: MapboxRouteLineOptions by lazy {
74+
MapboxRouteLineOptions.Builder(this)
75+
.withRouteLineResources(routeLineResources)
76+
.withRouteLineBelowLayerId("road-label")
77+
.build()
78+
}
79+
80+
private val routeLineView by lazy {
81+
MapboxRouteLineView(options)
82+
}
83+
84+
private val routeLineApi: MapboxRouteLineApi by lazy {
85+
MapboxRouteLineApi(options)
86+
}
87+
88+
private val routeArrowApi: MapboxRouteArrowApi by lazy {
89+
MapboxRouteArrowApi()
90+
}
91+
92+
private val routeArrowView: MapboxRouteArrowView by lazy {
93+
MapboxRouteArrowView(RouteArrowOptions.Builder(this).build())
94+
}
95+
96+
private val replayProgressObserver = ReplayProgressObserver(mapboxReplayer)
97+
98+
private val routeProgressObserver = RouteProgressObserver { routeProgress ->
99+
routeArrowApi.addUpcomingManeuverArrow(routeProgress).apply {
100+
routeArrowView.renderManeuverUpdate(mapboxMap.getStyle()!!, this)
101+
}
102+
}
103+
104+
private val locationObserver = object : LocationObserver {
105+
override fun onNewRawLocation(rawLocation: Location) {}
106+
override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
107+
navigationLocationProvider.changePosition(
108+
locationMatcherResult.enhancedLocation,
109+
locationMatcherResult.keyPoints,
110+
)
111+
if (isNavigating) {
112+
updateCamera(locationMatcherResult.enhancedLocation)
113+
}
114+
}
115+
}
116+
117+
private val routesObserver = RoutesObserver { result ->
118+
if (result.navigationRoutes.isNotEmpty()) {
119+
CoroutineScope(Dispatchers.Main).launch {
120+
routeLineApi.setNavigationRoutes(result.navigationRoutes).apply {
121+
routeLineView.renderRouteDrawData(mapboxMap.getStyle()!!, this)
122+
}
123+
}
124+
isNavigating = true
125+
startSimulation(result.navigationRoutes[0].directionsRoute)
126+
}
127+
}
128+
129+
private var adasisMessagesLog: String = "Received adasis messages:\n"
130+
private var numberOfMessages = 1
131+
132+
private fun init() {
133+
initNavigation()
134+
initStyle()
135+
}
136+
137+
@SuppressLint("MissingPermission")
138+
private fun initNavigation() {
139+
mapboxNavigation = MapboxNavigationProvider.create(
140+
NavigationOptions.Builder(this@AdasisActivity)
141+
.accessToken(getMapboxAccessTokenFromResources())
142+
.locationEngine(ReplayLocationEngine(mapboxReplayer))
143+
.build()
144+
)
145+
mapboxNavigation.registerLocationObserver(object : LocationObserver {
146+
override fun onNewRawLocation(rawLocation: Location) {
147+
updateCamera(rawLocation)
148+
navigationLocationProvider.changePosition(
149+
rawLocation,
150+
)
151+
mapboxNavigation.unregisterLocationObserver(this)
152+
}
153+
154+
override fun onNewLocationMatcherResult(
155+
locationMatcherResult: LocationMatcherResult,
156+
) {
157+
//
158+
}
159+
})
160+
mapboxNavigation.startTripSession()
161+
mapboxReplayer.pushRealLocation(this, 0.0)
162+
mapboxReplayer.play()
163+
}
164+
165+
@SuppressLint("MissingPermission")
166+
private fun initStyle() {
167+
mapboxMap.loadStyleUri(Style.MAPBOX_STREETS) { style ->
168+
routeLineView.initializeLayers(style)
169+
binding.mapView.gestures.addOnMapLongClickListener { point ->
170+
val currentLocation = navigationLocationProvider.lastLocation
171+
if (currentLocation != null) {
172+
waypointsController.add(point)
173+
val origin = Point.fromLngLat(
174+
currentLocation.longitude,
175+
currentLocation.latitude
176+
)
177+
findRoute(origin)
178+
}
179+
false
180+
}
181+
}
182+
}
183+
184+
@SuppressLint("DiscouragedApi")
185+
private fun getMapboxAccessTokenFromResources(): String {
186+
return getString(
187+
resources.getIdentifier("mapbox_access_token", "string", packageName)
188+
)
189+
}
190+
191+
private fun getMapCamera(): CameraAnimationsPlugin {
192+
return binding.mapView.camera
193+
}
194+
195+
@SuppressLint("MissingPermission")
196+
private fun startSimulation(route: DirectionsRoute) {
197+
mapboxReplayer.stop()
198+
mapboxReplayer.clearEvents()
199+
mapboxReplayer.pushRealLocation(this, 0.0)
200+
val replayEvents = ReplayRouteMapper().mapDirectionsRouteGeometry(route)
201+
mapboxReplayer.pushEvents(replayEvents)
202+
mapboxReplayer.seekTo(replayEvents.first())
203+
mapboxReplayer.play()
204+
}
205+
206+
private fun updateCamera(location: Location) {
207+
val mapAnimationOptionsBuilder = MapAnimationOptions.Builder()
208+
mapAnimationOptionsBuilder.duration(1500L)
209+
mapCamera.easeTo(
210+
CameraOptions.Builder()
211+
.center(Point.fromLngLat(location.longitude, location.latitude))
212+
.bearing(location.bearing.toDouble())
213+
.pitch(45.0)
214+
.zoom(17.0)
215+
.padding(EdgeInsets(1000.0, 0.0, 0.0, 0.0))
216+
.build(),
217+
mapAnimationOptionsBuilder.build()
218+
)
219+
}
220+
221+
private fun findRoute(origin: Point) {
222+
val coordinates = waypointsController.coordinates(origin)
223+
val routeOptions = RouteOptions.builder()
224+
.applyDefaultNavigationOptions()
225+
.applyLanguageAndVoiceUnitOptions(this)
226+
.coordinatesList(coordinates)
227+
.layersList(
228+
ArrayList<Int?>(coordinates.size).apply {
229+
add(mapboxNavigation.getZLevel())
230+
repeat(coordinates.size - 1) { add(null) }
231+
},
232+
)
233+
.build()
234+
235+
mapboxNavigation.requestRoutes(
236+
routeOptions,
237+
object : NavigationRouterCallback {
238+
override fun onRoutesReady(
239+
routes: List<NavigationRoute>,
240+
routerOrigin: RouterOrigin,
241+
) {
242+
mapboxNavigation.setNavigationRoutes(routes)
243+
}
244+
245+
override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
246+
// no impl
247+
}
248+
249+
override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) {
250+
// no impl
251+
}
252+
}
253+
)
254+
}
255+
256+
override fun onCreate(savedInstanceState: Bundle?) {
257+
super.onCreate(savedInstanceState)
258+
259+
binding = LayoutActivityAdasisBinding.inflate(layoutInflater)
260+
setContentView(binding.root)
261+
262+
mapboxMap = binding.mapView.getMapboxMap()
263+
binding.adasisMsgLog.text = adasisMessagesLog
264+
265+
locationComponent = binding.mapView.location.apply {
266+
setLocationProvider(navigationLocationProvider)
267+
enabled = true
268+
}
269+
mapCamera = getMapCamera()
270+
271+
init()
272+
}
273+
274+
@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
275+
override fun onStart() {
276+
super.onStart()
277+
if (::mapboxNavigation.isInitialized) {
278+
mapboxNavigation.registerRoutesObserver(routesObserver)
279+
mapboxNavigation.registerLocationObserver(locationObserver)
280+
mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
281+
mapboxNavigation.registerRouteProgressObserver(replayProgressObserver)
282+
283+
mapboxNavigation.setAdasisMessageCallback(
284+
AdasisConfig.Builder().build()
285+
) { messageBuffer, context ->
286+
this@AdasisActivity.runOnUiThread {
287+
// TODO decode buffer and print data
288+
adasisMessagesLog += "${numberOfMessages++}: ${messageBuffer.size} bytes\n"
289+
binding.adasisMsgLog.text = adasisMessagesLog
290+
binding.scrollContainer.fullScroll(View.FOCUS_DOWN)
291+
292+
Log.d(TAG, "Adasis message: $messageBuffer, context: $context")
293+
}
294+
}
295+
}
296+
}
297+
298+
@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
299+
override fun onStop() {
300+
super.onStop()
301+
mapboxNavigation.unregisterRoutesObserver(routesObserver)
302+
mapboxNavigation.unregisterLocationObserver(locationObserver)
303+
mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
304+
mapboxNavigation.unregisterRouteProgressObserver(replayProgressObserver)
305+
mapboxNavigation.resetAdasisMessageCallback()
306+
}
307+
308+
override fun onDestroy() {
309+
super.onDestroy()
310+
routeLineApi.cancel()
311+
routeLineView.cancel()
312+
mapboxReplayer.finish()
313+
mapboxNavigation.onDestroy()
314+
}
315+
316+
private companion object {
317+
val TAG = AdasisActivity::class.simpleName
318+
}
319+
}

0 commit comments

Comments
 (0)