Speed Watcher Simulated Navigation ¶
Setup ¶
Download the
SpeedWatcher
project
archive file or clone the project with Git
See the Configure Android Example guide.
Run the example ¶
In Android Studio, from the
File
menu, select
Sync
Project
with
Gradle
Files
|
|
|
How it works ¶

You can open the MainActivity.kt file to see how simulated navigation along a computed route with current speed and speed limit display works.
1private val navigationService = NavigationService()
A
NavigationService()
is instantiated, which carries out
both simulated navigation and real navigation.
1 private val navigationListener: NavigationListener
2 = NavigationListener.create(
3 onNavigationStarted = {
4 SdkCall.execute {
5 gemSurfaceView.mapView?.let { mapView ->
6 mapView.preferences?.enableCursor = false
7 navRoute?.let { route ->
8 mapView.presentRoute(route)
9 }
10 // Start listening for new positions.
11 PositionService().addListener(positionListener,
12 EDataType.Position)
13 enableGPSButton()
14 mapView.followPosition()
15 }
16 }
17 },
18 onNavigationInstructionUpdated = { instr ->
19 // From every new navigation instruction get the speed limit.
20 val limit = SdkCall.execute execute@{
21 val pair = GemUtil.getSpeedText(instr.currentStreetSpeedLimit,
22 EUnitSystem.Metric)
23 return@execute pair.first + " " + pair.second
24 }
25 speedLimit.text = limit
26 },
27 onDestinationReached = {
28 //remove the position listener when navigation is completed
29 PositionService().removeListener(positionListener)
30 }
31)
NavigationListener
receives event updates, or notifications, from the
navigation service, during navigation such as
when the destination is reached, or when the route to the desired destination
has been recomputed, because a detour away from the original route was taken.
onNavigationStarted
listener, the
onNavigationInstructionUpdated
listener is also instantiated,
to receive the speed limit which is included
with each instruction, for turns and other events along the route.
onDestinationReached
listener is instantiated to get a
notification upon arrival at the destination.
1 private val positionListener = object : PositionListener() {
2 override fun onNewPosition(value: PositionData) {
3 // Get the current speed for every new position received
4 val speed = GemUtil.getSpeedText(value.speed,
5 EUnitSystem.Metric).let { speedPair ->
6 speedPair.first + " " + speedPair.second
7 }
8 Util.postOnMain {
9 currentSpeed.text = speed
10 }
11 }
12 }
1private val routingProgressListener = ProgressListener.create(
2 onStarted = {
3 progressBar.visibility = View.VISIBLE
4 },
5 onCompleted = { _, _ ->
6 progressBar.visibility = View.GONE
7 },
8 postOnMain = true
9)
mapView.followPosition()
causes
the camera to follow the green arrow.
|
|||
1private fun enableGPSButton() {
2 // Set actions for entering/ exiting following position mode.
3 gemSurfaceView.mapView?.apply {
4 onExitFollowingPosition = {
5 followCursorButton.visibility = View.VISIBLE
6 }
7 onEnterFollowingPosition = {
8 followCursorButton.visibility = View.GONE
9 }
10 // Set on click action for the GPS button.
11 followCursorButton.setOnClickListener {
12 SdkCall.execute { followPosition() }
13 }
14 }
15}
enableGPSButton()
causes a round purple button to appear in the lower
right corner of the screen, whenever the simulation is active and
the camera is not following the green arrow. If the user pushes this button,
the
followPosition()
function is called, and thus the camera
starts to follow the green arrow once again.
1private fun startSimulation() = SdkCall.execute {
2 val waypoints = arrayListOf(
3 Landmark("Start", 48.526, 7.734),
4 Landmark("Destination", 41.645, -0.883)
5 )
6 navigationService.startSimulation(waypoints, navigationListener,
7 routingProgressListener,
8 speedMultiplier = 0.5f)
9}
speedMultiplier
=
0.5f
is there because in a simulation, the speed is
the same as the speed limit, so to have a different actual speed than the speed
limit during this simulation, as both are displayed, the speed is set to be
0.5, or half, of the speed limit.
1override fun onCreate(savedInstanceState: Bundle?) {
2 super.onCreate(savedInstanceState)
3 setContentView(R.layout.activity_main)
4 gemSurfaceView = findViewById(R.id.gem_surface)
5 progressBar = findViewById(R.id.progressBar)
6 currentSpeed = findViewById(R.id.current_speed)
7 speedLimit = findViewById(R.id.speed_limit)
8 followCursorButton = findViewById(R.id.followCursor)
9
10 SdkSettings.onMapDataReady = onMapDataReady@{ isReady ->
11 if (!isReady) return@onMapDataReady
12 // Defines an action that should be done when
13 // the world map is ready (Updated/ loaded).
14 startSimulation()
15 }
16 SdkSettings.onApiTokenRejected = {
17 Toast.makeText(this@MainActivity, "TOKEN REJECTED",
18 Toast.LENGTH_SHORT).show()
19 }
20 if (!Util.isInternetConnected(this)) {
21 Toast.makeText(this, "You must be connected to internet!",
22 Toast.LENGTH_LONG).show()
23 }
24}
MainActivity
overrides the
onCreate()
function which checks
that an internet connection is available and starts the simulation
when the map instantiation is complete (the map is ready).