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

1
package ai.nextbillion.navigation.demo.activity;
2
3
import android.location.Location;
4
import android.os.Bundle;
5
6
import ai.nextbillion.maps.Nextbillion;
7
import ai.nextbillion.maps.camera.CameraUpdate;
8
import ai.nextbillion.maps.camera.CameraUpdateFactory;
9
import ai.nextbillion.maps.core.MapView;
10
import ai.nextbillion.maps.core.NextbillionMap;
11
import ai.nextbillion.maps.core.OnMapReadyCallback;
12
import ai.nextbillion.maps.core.Style;
13
import ai.nextbillion.maps.geometry.LatLng;
14
import ai.nextbillion.maps.location.engine.LocationEngine;
15
import ai.nextbillion.maps.location.engine.LocationEngineCallback;
16
import ai.nextbillion.maps.location.engine.LocationEngineProvider;
17
import ai.nextbillion.maps.location.engine.LocationEngineRequest;
18
import ai.nextbillion.maps.location.engine.LocationEngineResult;
19
import ai.nextbillion.maps.location.modes.RenderMode;
20
import ai.nextbillion.navigation.demo.R;
21
import ai.nextbillion.navigation.ui.camera.CameraUpdateMode;
22
import ai.nextbillion.navigation.ui.camera.NavigationCameraUpdate;
23
import ai.nextbillion.navigation.ui.map.NavNextbillionMap;
24
25
import androidx.annotation.NonNull;
26
import androidx.annotation.Nullable;
27
import androidx.appcompat.app.AppCompatActivity;
28
29
import com.google.android.material.floatingactionbutton.FloatingActionButton;
30
31
import 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
39
public 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.

© 2024 NextBillion.ai all rights reserved.