Voice Instruction Simulated Navigation¶
In this guide you will learn how to simulate navigation
along a computed route rendered on an interactive map,
from a departure position to a desired destination.
The map is fully 3D, supporting pan, pinch-zoom,
rotate and tilt.
The navigation includes voice instructions in a
language of your choice.
Setup¶
First, get an API key token, see the
Getting Started guide.
Download the VoiceInstrRouteSimulation 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
An android device should be connected via USB cable.
Press SHIFT+F10 to compile, install and run the example on the
android device.
How it works¶
You can open the MainActivity.kt file to see how simulated navigation along a computed route with voice instructions works.
1private val navigationService = NavigationService()
A NavigationService()
is instantiated, which carries out
both simulated navigation and real navigation.
1private val navigationListener: NavigationListener = NavigationListener.create(
2 onNavigationStarted = { onNavigationStarted() },
3 onNavigationSound = { sound ->
4 SdkCall.execute {
5 SoundPlayingService.play(sound, playingListener, soundPreference)
6 }
7 },
8 canPlayNavigationSound = true,
9 postOnMain = true
10)
The
NavigationListener
receives event updates 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.Besides the
onNavigationStarted
listener, the onNavigationSound
listener is also instantiated, to receive the voice instructions for turns
and other events along the route, including warnings, such as about
speed cameras or exceeding the posted speed limit.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)
Define a listener to indicate when the route computation is completed,
so real or simulated navigation (simulated in this case) can start.
1private fun onNavigationStarted() = SdkCall.execute {
2 gemSurfaceView.mapView?.let { mapView ->
3 mapView.preferences?.enableCursor = false
4 navigationService.getNavigationRoute(navigationListener)?.let { route ->
5 mapView.presentRoute(route)
6 }
7 enableGPSButton()
8 mapView.followPosition()
9 }
10}
When navigation is started,
mapView.followPosition()
causes
the camera to follow the green arrow.If the user pans (moves) the map to another location,
the camera no longer follows 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, routingProgressListener)
7}
The starting, or departure point of the route is the first waypoint in a list of
2 or more Landmarks (2 in this case), each containing a name, latitude (in degrees)
and longitude (in degrees). The destination point is the last waypoint in the list.
1override fun onCreate(savedInstanceState: Bundle?) {
2 super.onCreate(savedInstanceState)
3 setContentView(R.layout.activity_main)
4 progressBar = findViewById(R.id.progressBar)
5 gemSurfaceView = findViewById(R.id.gem_surface)
6 followCursorButton = findViewById(R.id.followCursor)
7
8 SdkSettings.onMapDataReady = onMapDataReady@{ isReady ->
9 if (!isReady) return@onMapDataReady
10
11 SdkCall.execute {
12 contentStore = ContentStore()
13
14 val type = EContentType.HumanVoice
15 val countryCode = "IRL"
16 val onVoiceReady = { voiceFilePath: String ->
17 SdkSettings.setVoiceByPath(voiceFilePath)
18 startSimulation()
19 }
20 // check if already exists locally
21 contentStore?.getLocalContentList(type)?.let { localList ->
22 for (item in localList) {
23 if (item.countryCodes?.contains(countryCode) == true) {
24 onVoiceReady(item.filename!!)
25 return@execute // already exists
26 }
27 }
28 }
29 // download the voice
30 contentStore?.asyncGetStoreContentList(type, onCompleted =
31 { result, _, _ ->
32 SdkCall.execute {
33 for (item in result) {
34 if (item.countryCodes?.contains(countryCode) == true) {
35 item.asyncDownload(onCompleted = { _, _ ->
36 SdkCall.execute {
37 onVoiceReady(item.filename!!)
38 }
39 })
40 break
41 }
42 }
43 }
44 })
The
MainActivity
overrides the onCreate()
function which downloads
the voice from the server to be used for the voice instructions during the
simulated navigation.Note the 3-letter ISO countrycode
val countryCode = "IRL"
to specify which voice to download.A complete list of these country codes can be found here:
https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3