Initialize Navigation SDK
Navigation applications require many types of data that are constantly updated to provide information to the user. To being accessing this data you need to initialize the Navigation SDK and start a trip session. Then, you can use this data to power two kinds of navigation experiences: passive navigation (also known as free-drive mode) or active guidance (or turn-by-turn navigation).
Initialize the Navigation SDK
There are three steps you need to complete to initialize the Navigation SDK and begin receiving data:
- Provide an
access token
; - Create a
MapboxNavigation
object, which is the entry point for interacting with the SDK; - Start a trip session, which allows you to start consuming and processing data.
Access token
Visit the mapbox.com to get the Mapbox access token.
Add a mapbox_access_token.xml
file to your project to the following location: src/main/res/values/mapbox_access_token.xml
with the following contents:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="mapbox_access_token" translatable="false" tools:ignore="UnusedResources">MAPBOX_ACCESS_TOKEN</string>
</resources>
You can also set the token via:
MapboxOptions.accessToken = MAPBOX_ACCESS_TOKEN
and change it in runtime. First, the token from MapboxOptions
will be used. If it's not set, it will be read from resources.
Create the MapboxNavigation
object
The MapboxNavigation
object is the primary entity of the Navigation SDK and the producer of the majority of the data needed in a navigation application.
MapboxNavigation
is a singleton-like object, there should only be one instance running per application process. This object can be safely used across different activities and fragments, or accessed from a ViewModel
.The instance can also be safely destroyed and recreated if needed.To create the object use the MapboxNavigationApp
and pass the NavigationOptions
. MapboxNavigationApp
is essentially, a lifecycle reference counter. When an attached lifecycle is CREATED
, MapboxNavigationApp
will construct an instance of MapboxNavigation
and notify all registered MapboxNavigationObserver
.
1. Set up MapboxNavigationApp
You have many options for when or how to setup MapboxNavigationApp
. The easiest solution is to add it to your Application.onCreate
. The NavigationOptionsProvider
will request NavigationOptions
when an attached LifecycleOwner
is at least CREATED
.
if (!MapboxNavigationApp.isSetup()) {
MapboxNavigationApp.setup {
NavigationOptions.Builder(context)
// additional options
.build()
}
}
2. Attach LifecycleOwner
MapboxNavigationApp
will create MapboxNavigation
when at least one attached LifecycleOwner
is CREATED
. This accepts any LifecycleOwner
, like Activities or Fragments. It will also accept custom LifecycleOwner
s if you need a custom experience. MapboxNavigationObserver
will stay attached until both the car and app are destroyed, this makes for a seamless experience when your users change their Android Auto connection.
In this example, MapboxNavigation
will be attached when MyFragment
is CREATED
.
class MyFragment : Fragment {
override fun onCreateView() {
if (!MapboxNavigationApp.isSetup()) {
MapboxNavigationApp.setup {
NavigationOptions.Builder(context).build()
}
}
MapboxNavigationApp.attach(this)
}
}
In this example, MapboxNavigation
will be attached when the MyActivity
is RESUMED
.
class MyActivity : Activity {
init {
lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
MapboxNavigationApp.attach(owner)
}
override fun onPause(owner: LifecycleOwner) {
MapboxNavigationApp.detach(owner)
}
})
}
override fun onCreate() {
if (!MapboxNavigationApp.isSetup()) {
MapboxNavigationApp.setup {
NavigationOptions.Builder(context).build()
}
}
}
}
3. Registering MapboxNavigationObserver
Register the MapboxNavigationObserver
inside Lifecycle
callbacks, that will give MapboxNavigationObserver
the ability to control a specific definition. Following this pattern will also avoid memory leaks. For each lifecycle state, there is a corresponding destruction event that you can use to unregister the MapboxNavigationObserver
.
MapboxNavigationApp
will call MapboxNavigationObserver.onDetached
when the Application is stopped. The Android system will destroy the application process and reclaim resources used by the MapboxNavigationObserver
. You can control when the MapboxNavigationObserver
is attached with MapboxNavigationApp.attach(lifecycleOwner = *)
.MapboxNavigationApp.registerObserver | MapboxNavigationApp.unregisterObserver |
---|---|
Application.onCreate | unregister is optional |
onCreate | onDestroy |
onStart | onStop |
onResume | onPause |
MapboxNavigationObserver
can be registered when the resources are available.
class MyApplication : Application() {
init {
// The application context can be found in onAttached through
// mapboxNavigation.navigationOptions.applicationContext
MapboxNavigationApp.registerObserver(MyObserver())
}
override fun onCreate() {
super.onCreate()
// Or you can pass the applicationContext directly after the application is created
val observer = MyObserverWithContext(applicationContext)
MapboxNavigationApp.registerObserver(observer)
}
}
In this example, MapboxNavigation
will be attached when the LifecycleOwner
is RESUMED
.
private val myObserver = MyMapboxNavigationObserver()
lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
MapboxNavigationApp.registerObserver(myObserver)
}
override fun onPause(owner: LifecycleOwner) {
MapboxNavigationApp.unregisterObserver(myObserver)
}
})
4. Implement MapboxNavigationObserver
The MapboxNavigationObserver
is a lifecycle aware object. You can control when the onAttached
/ onDetached
calls will be triggered with MapboxNavigationApp.setup
, MapboxNavigationApp.attach(lifecycleOwner)
, and MapboxNavigationApp.register(mapboxNavigationObserver)
. The MapboxNavigationObserver
implementation handles declaring what it will do while it is attached. For example, the observer below will register onto the location observer.
class MyMapboxNavigationObserver : MapboxNavigationObserver {
private val locationObserver = MyLocationObserver()
val location: Flow<Location> = locationObserver.location()
override fun onAttached(mapboxNavigation: MapboxNavigation) {
mapboxNavigation.registerLocationObserver(locationObserver)
}
override fun onDetached(mapboxNavigation: MapboxNavigation) {
mapboxNavigation.unregisterLocationObserver(locationObserver)
}
}
Once the MapboxNavigation
object is initialized, the Navigation SDK starts in an internal idle
state. There's no location data being consumed or processed and no updates are generated.
Start a trip session
To start consuming and processing data, you need to start a trip session using startTripSession()
.
You can use MapboxNavigationApp
to access MapboxNavigation
synchronously anywhere in your application using the current()
function.
// when lifecycle state of any attached components is at least CREATED `current()` will return non-null instance.
val mapboxNavigation = MapboxNavigationApp.current()
mapboxNavigation?.startTripSession()
Also you can use a LifecycleOwner
extension.
val mapboxNavigation by requireMapboxNavigation()
// when lifecycle state is at least CREATED
mapboxNavigation.startTripSession()
When you start a session, the MapboxNavigation
object will:
- Request raw location updates from the
LocationProvider
passed inNavigationOptions#locationOptions
. Read more about using default and custom location providers in the Device location guide. - Process the incoming raw location updates and deliver various data observers updates with processed data.
When a trip session is running, there's also an Android foreground service running and displaying a notification so the Navigation SDK can keep receiving raw location updates, even if the app is minimized.
To shutdown the foreground location service and stop data processing, you need to stop a session by calling:
mapboxNavigation.stopTripSession()