Skip to main content

Navigation instructions

|

The Maps SDK for Android offers comprehensive real-time navigation guidance, providing detailed information on the current and upcoming route, including road details, street names, speed limits, and turn directions. It delivers essential data such as remaining travel time, distance to destination, and upcoming turn or road information, ensuring users receive accurate, timely instructions. Designed for both navigation and simulation scenarios, this feature enhances the overall user experience by supporting smooth and efficient route planning and execution.

The main class responsible for turn-by-turn live navigation guidance is the NavigationInstruction class.

info

It is important to distinguish between NavigationInstruction and RouteInstruction. NavigationInstruction offers real-time, turn-by-turn navigation based on the user's current position and is relevant only during navigation or simulation. In contrast, RouteInstruction provides an overview of the entire route available as soon as the route is calculated and the list of instructions do not change as the user navigates on the route.

Instantiating navigation instructions

Navigation instructions cannot be directly instantiated. Instead, they must be provided by the SDK while navigating. For detailed guidance on how to navigate on routes, refer to the Getting Started with Navigation Guide.

There are two main ways of getting a navigation instruction:

  • NavigationInstruction instances can be obtained via the callback provided as parameters to the startNavigation and startSimulation methods through the NavigationListener.
  • The NavigationService class provides a getNavigationInstruction method which returns the currently available navigation instruction. Make sure navigation/simulation is active before using the method provided above.

Import statements

To work with navigation instructions in your Android project, you'll need the following imports:

import com.magiclane.sdk.routesandnavigation.NavigationInstruction
import com.magiclane.sdk.routesandnavigation.NavigationListener
import com.magiclane.sdk.routesandnavigation.NavigationService
import com.magiclane.sdk.core.Rgba
import com.magiclane.sdk.util.GemUtilImages
import com.magiclane.sdk.util.SdkCall
import android.graphics.Bitmap
import android.widget.Toast

Getting navigation instructions through NavigationListener

The most common way to receive navigation instructions is through the NavigationListener.onNavigationInstructionUpdated callback:

private val navigationListener: NavigationListener = NavigationListener.create(
onNavigationInstructionUpdated = { instr ->
// Handle the navigation instruction
val currentStreetName = instr.currentStreetName
val nextTurnInstruction = instr.nextTurnInstruction

// Process instruction data...
}
)

Getting navigation instructions from NavigationService

You can also directly query the navigation service for the current instruction:

private val navigationService = NavigationService()

// Get current navigation instruction (ensure navigation is active)
val currentInstruction = navigationService.getNavigationInstruction()
MemberTypeDescription
currentCountryCodeISOString?Returns the ISO 3166-1 alpha-3 country code for the current navigation instruction. Empty string means no country.
currentStreetNameString?Returns the current street name.
currentStreetSpeedLimitDoubleReturns the maximum speed limit on the current street in meters per second. Returns 0 if not available.
driveSideEDriveSideReturns the drive side flag of the current traveled road.
hasNextNextTurnInfo()BooleanReturns true if next-next turn information is available.
hasNextTurnInfo()BooleanReturns true if next turn information is available.
instructionIndexIntReturns the index of the current route instruction on the current route segment.
laneImageImage?Returns a customizable image representation of current lane configuration. The user is responsible to verify if the image is valid.
navigationStatusENavigationStatusReturns the navigation/simulation status.
nextCountryCodeISOString?Returns the ISO 3166-1 alpha-3 country code for the next navigation instruction.
nextNextStreetNameString?Returns the next-next street name.
nextNextTurnDetailsTurnDetails?Returns the full details for the next-next turn. Used for customizing turn display in UI.
nextNextTurnInstructionString?Returns the textual description for the next-next turn.
nextStreetNameString?Returns the next street name.
nextTurnDetailsTurnDetails?Returns the full details for the next turn. Used for customizing turn display in UI.
nextTurnInstructionString?Returns the textual description for the next turn.
remainingTravelTimeDistanceTimeDistance?Returns the remaining travel time in seconds and distance in meters.
remainingTravelTimeDistanceToNextWaypointTimeDistance?Returns the remaining travel time in seconds and distance in meters to the next waypoint.
currentRoadInformationList<RoadInfo>?Returns the current road information list.
nextRoadInformationList<RoadInfo>?Returns the next road information list.
nextNextRoadInformationList<RoadInfo>?Returns the next-next road information list.
segmentIndexIntReturns the index of the current route segment.
signpostDetailsSignpostDetails?Returns the extended signpost details.
signpostInstructionString?Returns the textual description for the signpost information.
timeDistanceToNextNextTurnTimeDistance?Returns the time (seconds) and distance (meters) to the next-next turn. Returns values for next turn if no next-next turn available.
timeDistanceToNextTurnTimeDistance?Returns the time (seconds) and distance (meters) to the next turn.
traveledTimeDistanceTimeDistance?Returns the traveled time in seconds and distance in meters.

The field nextTurnInstruction provides an instruction in text format, suitable for displaying on UI. Please use the onNavigationSound callback in NavigationListener for getting an instruction suitable for text-to-speech.

Turn details

Next turn details

The following snippet shows how to extract detailed instructions for the next turn along the route. It's typically used in the navigation UI to show users the upcoming maneuver. You may also use this to provide turn-by-turn instructions with images or detailed text for navigation display:

// If hasNextTurnInfo() is false some details are not available
val hasNextTurnInfo = navigationInstruction.hasNextTurnInfo()

if (hasNextTurnInfo) {
// The next turn instruction
val nextTurnInstruction = navigationInstruction.nextTurnInstruction

// The next turn details
val turnDetails = navigationInstruction.nextTurnDetails

turnDetails?.let {
// Turn event type (continue straight, turn right, turn left, etc.)
val event = it.event

// Roundabout exit number (-1 if not a roundabout)
val roundaboutExitNumber = it.roundaboutExitNumber

// Get turn image using GemUtilImages
val turnImageSize = 300
val turnImage = getNextTurnImage(navigationInstruction, turnImageSize, turnImageSize)
}
}

// Helper function to get turn image (based on sample code)
private fun getNextTurnImage(
navInstr: NavigationInstruction,
width: Int,
height: Int
): Bitmap? {
return SdkCall.execute {
if (!navInstr.hasNextTurnInfo()) return@execute null

val image = navInstr.nextTurnDetails?.abstractGeometryImage

val aInner = Rgba(255, 255, 255, 255)
val aOuter = Rgba(0, 0, 0, 255)
val iInner = Rgba(128, 128, 128, 255)
val iOuter = Rgba(128, 128, 128, 255)

GemUtilImages.asBitmap(image, width, height, aInner, aOuter, iInner, iOuter)
}
}

See the TurnDetails guide for more details about the fields within the TurnDetails class.

Next next turn details

Details about the subsequent turn (i.e., the turn following the next one) can be crucial for certain use cases, such as providing a preview of upcoming maneuvers. These details can be accessed in a similar manner:

// If hasNextNextTurnInfo() is false some details are not available
val hasNextNextTurnInfo = navigationInstruction.hasNextNextTurnInfo()

if (hasNextNextTurnInfo) {
val nextNextTurnInstruction = navigationInstruction.nextNextTurnInstruction

val nextNextTurnDetails = navigationInstruction.nextNextTurnDetails

// Get next next turn image similarly to next turn image
nextNextTurnDetails?.let {
val nextNextTurnImage = getNextNextTurnImage(navigationInstruction, 300, 300)
}
}

// Helper function for next next turn image
private fun getNextNextTurnImage(
navInstr: NavigationInstruction,
width: Int,
height: Int
): Bitmap? {
return SdkCall.execute {
if (!navInstr.hasNextNextTurnInfo()) return@execute null

val image = navInstr.nextNextTurnDetails?.abstractGeometryImage

val aInner = Rgba(255, 255, 255, 255)
val aOuter = Rgba(0, 0, 0, 255)
val iInner = Rgba(128, 128, 128, 255)
val iOuter = Rgba(128, 128, 128, 255)

GemUtilImages.asBitmap(image, width, height, aInner, aOuter, iInner, iOuter)
}
}

The hasNextNextTurnInfo() might be false if the next instruction is the destination. The same operations discussed earlier for the next turn details can also be applied to the subsequent turn details.

Street information

Current street information

The following snippet shows how to get information about the current road:

// Current street name
val currentStreetName = navigationInstruction.currentStreetName

// Road info related to the current road
val currentRoadInfo = navigationInstruction.currentRoadInformation

// Country ISO code
val countryCode = navigationInstruction.currentCountryCodeISO

// The drive direction (left or right)
val driveDirection = navigationInstruction.driveSide

It is important to note that some streets may not have an assigned name. In such cases, currentStreetName will return null. The RoadInfo class offers additional details, including the road name and shield type, which correspond to the official codes or names assigned to a road.

For example, the currentStreetName might return "Bloomsbury Street," while the roadname field in the associated RoadInfo instance could provide the official designation, such as "A400." This distinction ensures comprehensive road identification.

Next & next next street information

Information about the next street, as well as the street following it (next-next street), can also be retrieved. These details include the street name, type, and other associated metadata, enabling enhanced navigation and situational awareness:

// Street name
val nextStreetName = navigationInstruction.nextStreetName
val nextNextStreetName = navigationInstruction.nextNextStreetName

// Road info
val nextRoadInformation = navigationInstruction.nextRoadInformation
val nextNextRoadInformation = navigationInstruction.nextNextRoadInformation

// Next country iso code
val nextCountryCodeISO = navigationInstruction.nextCountryCodeISO

The fields associated with these streets retain the same meanings as discussed earlier about the current street.

danger

Ensure that hasNextTurnInfo() and hasNextNextTurnInfo() are true before attempting to access the respective fields. This verification prevents errors and ensures the availability of reliable data for the requested information.

Speed limit information

The NavigationInstruction class not only provides information about the current road's speed limit but also offers details about upcoming speed limits within a specified distance, assuming the user adheres to the recommended navigation route.

The following snippet demonstrates how to retrieve these details and handle various scenarios appropriately:

SdkCall.execute {
// The current street speed limit in m/s (0.0 if not available)
val currentStreetSpeedLimit = navigationInstruction.currentStreetSpeedLimit
}

Lane image

The lane image can be used to more effectively illustrate the correct lane for upcoming turns, providing clearer guidance:

val laneImage = navigationInstruction.laneImage

// Helper function to get lane image (based on sample code)
private fun getLaneInfoImage(
navInstr: NavigationInstruction,
width: Int,
height: Int
): Pair<Int, Bitmap?> {
return SdkCall.execute {
var resultWidth = width
if (resultWidth == 0)
resultWidth = (2.5 * height).toInt()

val bkColor = Rgba(118, 99, 200, 255)
val activeColor = Rgba(255, 255, 255, 255)
val inactiveColor = Rgba(24, 33, 21, 255)

val image = navInstr.laneImage

val resultPair = GemUtilImages.asBitmap(
image,
resultWidth,
height,
bkColor,
activeColor,
inactiveColor
)

// resultPair is Pair<Int, Bitmap?> where first is error code, second is bitmap
val errorCode = resultPair.first
val bitmap = resultPair.second

return@execute Pair(errorCode, bitmap)
} ?: Pair(-1, null)
}

// Usage example
val laneImageData = getLaneInfoImage(navigationInstruction, 500, 300)
val errorCode = laneImageData.first
val laneImageBitmap = laneImageData.second

if (errorCode == 0 && laneImageBitmap != null) {
// Successfully obtained lane image bitmap
// Use laneImageBitmap for display
} else {
// Handle error case
println("Failed to get lane image, error code: $errorCode")
}

Below is an example of a rendered lane image:

Lane image containing three lanes

Change the language of the instructions

The texts used in navigation instructions and related classes follow the language set in the SDK. See the internationalization guide for more details.