Skip to main content

User notifications

If your application is in the background or the screen is locked during turn-by-turn navigation, NavigationViewController can automatically display local user notifications to inform the user of upcoming maneuvers. These notifications contain the same information as the instruction banners that would be visible on the screen if your application were in the foreground. Tapping on a notification brings NavigationViewController back to the foreground.

Asking for permission to display notifications

The user needs to allow your application to display local user notifications. At some point before presenting NavigationViewController, such as when the application launches, ask the user for permission by calling the UNUserNotificationCenter.requestAuthorization(options:) method:

let center = UNUserNotificationCenter.current()
do {
try await center.requestAuthorization(options: [.alert, .sound, .badge])
} catch {
// Handle the error here.
}
// A possible place to request location permission.

As long as your application is allowed to display user notifications, NavigationViewController displays them at the same time as spoken instructions. If you want the user to receive notifications from another part of your application but not from NavigationViewController, set the sendsNotifications property to false.

Displaying notifications manually

Your application can also manually display user notifications about the navigation session. For example, you can use a notification to inform the user about application-specific aspects of the trip or to have more fine-grained control over their timing. Manually displayed notifications can also be part of a custom turn-by-turn navigation interface that does not use NavigationViewController.

To manually display a user notification, subscribe to the mapboxNavigation.navigation().voiceInstructions publisher. It posts events that the user passes the appropriate point at which to announce a spoken instruction. Inside your code, populate a UNMutableNotificationContent using the current visual instruction, which you can get using the RouteProgress.currentLegProgress, RouteLegProgress.currentStep, and RouteStep.instructionsDisplayedAlongStep properties.

mapboxNavigation.navigation().voiceInstructions
.sink { [weak self] status in
guard let self else { return }

scheduleLocalNotification(status.spokenInstruction)
}
.store(in: &subscriptions)

Then schedule this notification locally.

func scheduleLocalNotification(_ spokenInstruction: SpokenInstruction) {
let localNotificationCenter = UNUserNotificationCenter.current()
let identifier = "your_local_notification_identifier"
localNotificationCenter.removePendingNotificationRequests(withIdentifiers: [identifier])
localNotificationCenter.removeDeliveredNotifications(withIdentifiers: [identifier])

guard UIApplication.shared.applicationState == .background else { return }

let content = UNMutableNotificationContent()
content.title = spokenInstruction.text

let notificationRequest = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
localNotificationCenter.add(notificationRequest, withCompletionHandler: nil)
}
Was this page helpful?