Track current location on NavNextbillionMap

This example shows how to request and update user location on NavNextbillionMap.

  • Activity will get and display the user's location on a map once the map is loaded successfully

  • A floating button is provided on the screen, each time user clicks on the button, the camera will focus and zoom to the user's current location

In this example we do not handle location permission requests, you can refer to the official guide for assistance: https://developer.android.com/training/location/permissions

docs-image

For all code examples, refer to Navigation Code Examples

activity_track_current_location.xml view source

1<?xml version="1.0" encoding="utf-8"?>
2<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".activity.TrackCurrentLocationActivity">
8
9 <ai.nextbillion.maps.core.MapView
10 android:id="@+id/mapView_get_location"
11 android:layout_width="match_parent"
12 android:layout_height="match_parent"
13 app:nbmap_uiAttribution="false" />
14
15 <com.google.android.material.floatingactionbutton.FloatingActionButton
16 android:id="@+id/get_location"
17 android:layout_width="wrap_content"
18 android:layout_height="wrap_content"
19 android:layout_gravity="end|bottom"
20 android:layout_margin="16dp"
21 app:srcCompat="@drawable/ic_get_location" />
22
23</androidx.coordinatorlayout.widget.CoordinatorLayout>

TrackCurrentLocationActivity view source

1package ai.nextbillion.navigation.demo.activity;
2
3import android.location.Location;
4import android.os.Bundle;
5
6import ai.nextbillion.maps.Nextbillion;
7import ai.nextbillion.maps.camera.CameraUpdate;
8import ai.nextbillion.maps.camera.CameraUpdateFactory;
9import ai.nextbillion.maps.core.MapView;
10import ai.nextbillion.maps.core.NextbillionMap;
11import ai.nextbillion.maps.core.OnMapReadyCallback;
12import ai.nextbillion.maps.core.Style;
13import ai.nextbillion.maps.geometry.LatLng;
14import ai.nextbillion.maps.location.engine.LocationEngine;
15import ai.nextbillion.maps.location.engine.LocationEngineCallback;
16import ai.nextbillion.maps.location.engine.LocationEngineProvider;
17import ai.nextbillion.maps.location.engine.LocationEngineRequest;
18import ai.nextbillion.maps.location.engine.LocationEngineResult;
19import ai.nextbillion.maps.location.modes.RenderMode;
20import ai.nextbillion.navigation.demo.R;
21import ai.nextbillion.navigation.ui.camera.CameraUpdateMode;
22import ai.nextbillion.navigation.ui.camera.NavigationCameraUpdate;
23import ai.nextbillion.navigation.ui.map.NavNextbillionMap;
24
25import androidx.annotation.NonNull;
26import androidx.annotation.Nullable;
27import androidx.appcompat.app.AppCompatActivity;
28
29import com.google.android.material.floatingactionbutton.FloatingActionButton;
30
31import java.lang.ref.WeakReference;
32
33/***
34 * The example shows how to request user location and display on our MapView
35 * it assumes that you have granted location permissions for your application.
36 * if location permission is not granted, the demo code will not be able to fetch device location properly
37 */
38
39public class TrackCurrentLocationActivity extends AppCompatActivity implements OnMapReadyCallback {
40 private static final int CAMERA_ANIMATION_DURATION = 1000;
41 private static final int DEFAULT_CAMERA_ZOOM = 16;
42 private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
43 private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 500;
44
45 private MapView mapView;
46 private FloatingActionButton floatingActionButton;
47 private NavNextbillionMap nbMap;
48 private final TrackCurrentLocationCallback callback = new TrackCurrentLocationCallback(this);
49 private LocationEngine locationEngine;
50 private Location lastLocation;
51
52 @Override
53 protected void onCreate(@Nullable Bundle savedInstanceState) {
54 super.onCreate(savedInstanceState);
55 setContentView(R.layout.activity_track_current_location);
56 mapView = findViewById(R.id.mapView_get_location);
57 mapView.onCreate(savedInstanceState);
58 mapView.getMapAsync(this);
59
60 setUpFloatingButton();
61 }
62
63 private void setUpFloatingButton() {
64 floatingActionButton = findViewById(R.id.get_location);
65 floatingActionButton.setOnClickListener(v -> animateCamera());
66 }
67
68 // This function demonstrate how to focus camera to user location with certain zoom level
69 private void animateCamera() {
70 if (lastLocation != null) {
71 CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()), DEFAULT_CAMERA_ZOOM);
72 NavigationCameraUpdate navigationCameraUpdate = new NavigationCameraUpdate(cameraUpdate);
73 navigationCameraUpdate.setMode(CameraUpdateMode.OVERRIDE);
74 nbMap.retrieveCamera().update(navigationCameraUpdate, CAMERA_ANIMATION_DURATION);
75 }
76 }
77
78 @Override
79 public void onMapReady(@NonNull NextbillionMap nextbillionMap) {
80 nextbillionMap.setStyle(new Style.Builder().fromUri("https://api.nextbillion.io/maps/streets/style.json"));
81 nextbillionMap.getStyle(style -> {
82 nbMap = new NavNextbillionMap(mapView, nextbillionMap);
83 nbMap.updateLocationLayerRenderMode(RenderMode.GPS);
84 initializeLocationEngine();
85 });
86 }
87
88 private void onLocationFound(Location location) {
89 lastLocation = location;
90 nbMap.updateLocation(location);
91 }
92
93 private LocationEngineRequest buildEngineRequest() {
94 return new LocationEngineRequest.Builder(UPDATE_INTERVAL_IN_MILLISECONDS)
95 .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
96 .setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS)
97 .build();
98 }
99
100 @SuppressWarnings({"MissingPermission"})
101 private void initializeLocationEngine() {
102 // here we use location engine to update user current location
103 locationEngine = LocationEngineProvider.getBestLocationEngine(getApplicationContext());
104 LocationEngineRequest request = buildEngineRequest();
105 locationEngine.requestLocationUpdates(request, callback, null);
106 locationEngine.getLastLocation(callback);
107 }
108
109 private static class TrackCurrentLocationCallback implements LocationEngineCallback<LocationEngineResult> {
110
111 private final WeakReference<TableRowackCurrentLocationActivity> activityWeakReference;
112
113 TrackCurrentLocationCallback(TrackCurrentLocationActivity activity) {
114 this.activityWeakReference = new WeakReference<>(activity);
115 }
116
117 @Override
118 public void onSuccess(LocationEngineResult locationEngineResult) {
119 TrackCurrentLocationActivity activity = activityWeakReference.get();
120 if (activity != null) {
121 Location location = locationEngineResult.getLastLocation();
122 if (location == null) {
123 return;
124 }
125 activity.onLocationFound(location);
126 }
127 }
128
129 @Override
130 public void onFailure(@NonNull Exception e) {
131
132 }
133 }
134
135
136 @Override
137 public void onStart() {
138 super.onStart();
139 mapView.onStart();
140 }
141
142 @SuppressWarnings({"MissingPermission"})
143 @Override
144 public void onResume() {
145 super.onResume();
146 mapView.onResume();
147 if (locationEngine != null) {
148 locationEngine.requestLocationUpdates(buildEngineRequest(), callback, null);
149 }
150 }
151
152 @Override
153 public void onLowMemory() {
154 super.onLowMemory();
155 mapView.onLowMemory();
156 }
157
158 @Override
159 public void onPause() {
160 super.onPause();
161 mapView.onPause();
162 if (locationEngine != null) {
163 locationEngine.removeLocationUpdates(callback);
164 }
165 }
166
167 @Override
168 public void onStop() {
169 super.onStop();
170 mapView.onStop();
171 }
172
173 @Override
174 protected void onDestroy() {
175 super.onDestroy();
176 mapView.onDestroy();
177 }
178}

Code Highlights

  • The mapView.getMapAsync() function will trigger the onMapReady() override function, and we set the map style and mode here.

  • The location engine initialization is also done in the onMapReady() function, it will try to get the device's last known location, then use nbMap.updateLocation() to show the location info on map

  • The code example also uses a float button to adjust the camera position and zoom level to provide a better visual experience to the user.

Code summary

The code snippet is for an Android activity that tracks the current location of the user and displays it on a map. The activity first creates a MapView object and sets its onCreate() listener. The onCreate() listener then gets the map's getStyle() and uses it to create a NavNextbillionMap object. The NavNextbillionMap object is then used to update the map's location layer render mode to RenderMode.GPS.

The activity then creates a LocationEngine object and requests location updates from it. The location updates are received by the TrackCurrentLocationCallback object, which updates the map's location with the latest location information.

The activity also has a FloatingActionButton object that is used to focus the camera on the user's current location. When the FloatingActionButton is clicked, the activity calls the animateCamera() method, which focuses the camera on the user's current location.

The activity implements the following lifecycle methods:

onStart(): This method is called when the activity starts. It calls the onStart() method of the MapView object.

onResume(): This method is called when the activity resumes. It calls the onResume() method of the MapView object and requests location updates from the LocationEngine object.

onLowMemory(): This method is called when the device is low on memory. It calls the onLowMemory() method of the MapView object.

onPause(): This method is called when the activity pauses. It calls the onPause() method of the MapView object and removes location updates from the LocationEngine object.

onStop(): This method is called when the activity stops. It calls the onStop() method of the MapView object.

onDestroy(): This method is called when the activity is destroyed. It calls the onDestroy() method of the MapView object.

The activity also uses the following constants:

CAMERA_ANIMATION_DURATION: This constant is the duration of the animation used to focus the camera on the user's current location.

DEFAULT_CAMERA_ZOOM: This constant is the default zoom level of the map.

UPDATE_INTERVAL_IN_MILLISECONDS: This constant is the interval at which the LocationEngine object requests location updates.

FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS: This constant is the minimum interval at which the LocationEngine object requests location updates.

The activity uses the following classes:

  • MapView: This class represents a map view.

  • FloatingActionButton: This class represents a floating action button.

  • NextbillionMap: This class represents a Nextbillion map.

  • LocationEngine: This class provides access to location services.

  • LocationEngineRequest: This class represents a request for location updates.

  • LocationEngineResult: This class represents the result of a location update request.

  • TrackCurrentLocationCallback: This class implements the LocationEngineCallback interface and is used to receive location updates.