Showing device location

Showing the user's current location as a map annotation is a popular and often critical feature of location-based apps. The Maps SDK's LocationComponent makes use of the Maps SDK's runtime styling capabilities to display the device location icon within the map itself rather than on top as a simple Android view. Mapbox map layers and layer styling give you precise control, if you want it, of the way that a device's location is shown on the map.

help
Note

This LocationComponent has replaced the now-deprecated Location Layer Plugin. The LocationComponent is integrated into the Maps SDK for Android so that you don't need to add additional dependencies. It brings the same set of functionality that you were used to with the plugin.

Requesting location permissions

You'll need to request the Android-system location permission before using the LocationComponent. If your Android project is built targeting API level 23 or higher your application will need to request permissions during runtime. Handling this directly in your activity produces boilerplate code and can often be hard to manage. Read more about using the Mapbox Core Library for Android's PermissionsManager class.

Activating

MapboxMap#getLocationComponent() fetches the component and LocationComponent#activateLocationComponent() activates it. Both need to be called before any other LocationComponent adjustments, such as its visibility, are performed.

Retrieve and activate the LocationComponent once the user has granted location permission and the map has fully loaded.

@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {
enableLocationComponent();
}
});
}
@SuppressWarnings( {"MissingPermission"})
private void enableLocationComponent() {
// Check if permissions are enabled and if not request
if (PermissionsManager.areLocationPermissionsGranted(this)) {
// Get an instance of the component
LocationComponent locationComponent = mapboxMap.getLocationComponent();
// Activate with options
locationComponent.activateLocationComponent(this, mapboxMap.getStyle());
// Enable to make component visible
locationComponent.setLocationComponentEnabled(true);
// Set the component's camera mode
locationComponent.setCameraMode(CameraMode.TRACKING);
// Set the component's render mode
locationComponent.setRenderMode(RenderMode.COMPASS);
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}

Visibility

There is a single method to either enable or disable the LocationComponent's visibility after activation. The setLocationComponentEnabled() method requires a true/false boolean parameter. When set to false, this method will hide the device location icon and cease map camera animations from occurring.

locationComponent.setLocationComponentEnabled(true);

Customization

The LocationComponent can be customized in many different ways. You can set the image drawables, opacities, colors, and more. See a full list of XML attributes for styling the LocationComponent via XML. The LocationComponentOptions class can be used if you prefer to customize the LocationComponent programatically. Create a LocationComponentOptions object and then use whichever LocationComponentOptions.builder()'s various methods you'd like. Then use the built LocationComponentOptions object either while activating the component or by passing it through as a parameter of the LocationComponent#applyStyle() method at a later time.

LocationComponentOptions options = LocationComponentOptions.builder(this)
.layerBelow(layerId)
.foregroundDrawable(R.drawable.drawable_name)
.bearingTintColor(int color)
.accuracyAlpha(float)
.build();
locationComponent = mapboxMap.getLocationComponent();
locationComponent.activateLocationComponent(this, mapStyle, options);

Active styling options:

XML OptionExplanation
mapbox_foregroundDrawableDrawable image which would replace the dark blue circle
mapbox_foregroundTintColorThe dark blue circle
mapbox_backgroundDrawableDrawable image which would replace the white circle
mapbox_backgroundTintColorWhite circle
mapbox_bearingDrawableDrawable image which would replace the blue arrow point
mapbox_bearingTintColorBlue arrow point
mapbox_navigationDrawableDrawable image used for the navigation state icon
mapbox_accuracyAlphaThe larger light blue circle surrounding the device location icon
mapbox_accuracyColorColor of the larger light blue circle surrounding the device location icon
mapbox_elevationThe amount of space between the map and the device location icon. The elevation will adjust the size of the shadow as seen underneath the white circle
mapbox_compassAnimationEnabledEnable or disable smooth animation of compass values for the blue arrow point
mapbox_accuracyAnimationEnabledEnable or disable smooth animation of the larger light blue accuracy circle surrounding the device location icon

Stale styling options:

XML OptionExplanation
mapbox_foregroundDrawableStaleDrawable image which would replace the grey circle
mapbox_foregroundStaleTintColorGrey circle
mapbox_backgroundDrawableStaleWhite circle underneath the grey circle
mapbox_backgroundStaleTintColorDrawable image which would replace the white circle

RenderMode

The RenderMode class contains preset options for the device location image.

locationComponent.setRenderMode(RenderMode.NORMAL);

There are three types of RenderMode options:

RenderModeDescription
NORMALThis mode shows the device location, ignoring both compass and GPS bearing (no arrow rendered).
COMPASSThis mode shows the device location, as well as an arrow that is considering the compass of the device.
GPSThis mode shows the device location with the icon bearing updated from the Location updates being provided to the LocationComponent.
help
Note

The actual device location icon is highly customizable with methods such as LocationComponentOptions#foregroundDrawable() and LocationComponentOptions#backgroundDrawable().

CameraMode

The method LocationComponent#setCameraMode(@CameraMode.Mode int cameraMode) allows developers to set specific camera tracking instructions as the device location changes.

locationComponent.setCameraMode(CameraMode.TRACKING);

There are currently 7 CameraMode options available:

CameraModeDescription
NONENo camera tracking.
NONE_COMPASSCamera does not track location, but does track compass bearing.
NONE_GPSCamera does not track location, but does track GPS Location bearing.
TRACKINGCamera tracks the device location, no bearing is considered.
TRACKING_COMPASSCamera tracks the device location, tracking bearing provided by the device compass.
TRACKING_GPSCamera tracks the device location, with bearing provided by a normalized Location#getBearing().
TRACKING_GPS_NORTHCamera tracks the device location, with bearing always set to north (0).

Here are a few examples from the LocationModesActivity in the Maps SDK's test application:

CameraMode.NORMAL

CameraMode.COMPASS

CameraMode.GPS

Traditional camera transitions will be canceled when any of the camera modes, besides CameraMode#NONE, are engaged. Use LocationComponent#zoomWhileTracking and LocationComponent#tiltWhileTracking to manipulate the camera in a tracking state. Use these two in combination with traditional camera transitions and MapboxMap#CancelableCallback to schedule fluid transitions.

When instantiating the LocationComponent for the first time, the map's max/min zoom levels will be set toLocationComponentOptions#MAX_ZOOM_DEFAULT and LocationComponentOptions#MIN_ZOOM_DEFAULT respectively. Adjust the zoom range with the LocationComponentOptions#maxZoom() and LocationComponentOptions#minZoom() methods in the LocationComponentOptions class.

Gesture thresholds while camera tracking

The LocationComponent is integrated with the Mapbox Gestures for Android library. The component will adjust the camera's focal point and increase thresholds to enable camera manipulation, like zooming in and out, without breaking tracking. Enabling this feature is explicitly opt-in because it overwrites custom gestures detection implementation set with MapboxMap#setGesturesManager(AndroidGesturesManager, boolean, boolean).

To enable the feature use LocationComponentOptions#trackingGesturesManagement(boolean).

You can adjust thresholds that need to be exceeded in order to break the tracking for one pointer gestures (like panning the map, double-tap to zoom in) and multi-pointer gestures (like scale gesture, two-tap to zoom out):

  • LocationComponentOptions#trackingInitialMoveThreshold(float) adjusts the minimum single pointer movement in pixels required to break camera tracking.
  • LocationComponentOptions#trackingMultiFingerMoveThreshold(float) adjusts minimum multi pointer movement in pixels required to break camera tracking (for example during scale gesture).
  • If either of these thresholds are exceeded and tracking is dismissed, developers can listen to this with a OnCameraTrackingChangedListener:
LocationComponent locationComponent = mapboxMap.getLocationComponent();
locationComponent.addOnCameraTrackingChangedListener(new OnCameraTrackingChangedListener() {
@Override
public void onCameraTrackingDismissed() {
// Tracking has been dismissed
}
@Override
public void onCameraTrackingChanged(int currentMode) {
// CameraMode has been updated
}
});