In this page

Location Tracking Modes

这篇文档目前尚未提供译文,将以原文展示。

This example shows how to Switch Location Tracking Modes

  1. Location Permissions Handling

  2. Switch Location component RenderMode

  3. Switch Location Tracking Camera Mode

  4. Enable/Disable Location Component

  5. Tracking Current Location Automatically when MapReady

    1. locationComponent.setLocationComponentEnabled(true);
    2. locationComponent.setRenderMode(RenderMode.COMPASS);
    3. locationComponent.setCameraMode(CameraMode.TRACKING);

For all code examples, refer to Android Maps SDK Code Examples

activity_location_modes.xml view source

1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout 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
8    <ai.nextbillion.maps.core.MapView
9        android:id="@+id/mapView"
10        android:layout_width="match_parent"
11        android:layout_height="match_parent"
12        android:layout_marginBottom="0dp"
13        app:layout_constraintBottom_toTopOf="parent"
14        app:layout_constraintLeft_toLeftOf="parent"
15        app:layout_constraintRight_toRightOf="parent"
16        app:layout_constraintTop_toTopOf="parent"
17        app:nbmap_uiAttribution="false" />
18
19    <View
20        android:id="@+id/view_protected_gesture_area"
21        android:layout_width="0dp"
22        android:layout_height="0dp"
23        android:alpha="0.5"
24        android:background="@android:color/holo_red_light"
25        app:layout_constraintStart_toStartOf="@id/mapView"
26        app:layout_constraintTop_toTopOf="@id/mapView" />
27
28    <LinearLayout
29        android:id="@+id/linearLayout"
30        style="?android:attr/buttonBarStyle"
31        android:layout_width="0dp"
32        android:layout_height="wrap_content"
33        android:background="@color/palette_mint_100"
34        android:orientation="horizontal"
35        android:weightSum="4"
36        app:layout_constraintBottom_toBottomOf="parent"
37        app:layout_constraintLeft_toLeftOf="parent"
38        app:layout_constraintRight_toRightOf="parent"
39        tools:layout_constraintBottom_creator="1"
40        tools:layout_constraintLeft_creator="1"
41        tools:layout_constraintRight_creator="1">
42
43        <TextView
44            android:id="@+id/tv_mode"
45            android:layout_width="0dp"
46            android:layout_height="match_parent"
47            android:layout_weight=".75"
48            android:gravity="center"
49            android:text="Mode:"
50            android:textColor="@color/white"
51            android:textSize="18sp"
52            android:textStyle="bold" />
53
54        <Button
55            android:id="@+id/button_location_mode"
56            style="?android:attr/buttonBarButtonStyle"
57            android:layout_width="0dp"
58            android:layout_height="wrap_content"
59            android:layout_weight="1.25"
60            android:gravity="center"
61            android:text="Normal"
62            android:textColor="@android:color/white" />
63
64        <TextView
65            android:id="@+id/tv_tracking"
66            android:layout_width="0dp"
67            android:layout_height="match_parent"
68            android:layout_weight=".85"
69            android:gravity="center"
70            android:text="Tracking:"
71            android:textColor="@color/white"
72            android:textSize="18sp"
73            android:textStyle="bold" />
74
75        <Button
76            android:id="@+id/button_location_tracking"
77            style="?android:attr/buttonBarButtonStyle"
78            android:layout_width="0dp"
79            android:layout_height="wrap_content"
80            android:layout_weight="1.15"
81            android:gravity="center"
82            android:text="None"
83            android:textColor="@android:color/white" />
84
85    </LinearLayout>
86
87</androidx.constraintlayout.widget.ConstraintLayout>

LocationModesActivity view source

1package ai.nextbillion;
2
3import android.annotation.SuppressLint;
4import android.graphics.RectF;
5import android.location.Location;
6import android.os.Bundle;
7import android.view.Menu;
8import android.view.MenuItem;
9import android.view.View;
10import android.widget.ArrayAdapter;
11import android.widget.Button;
12import android.widget.Toast;
13
14import java.util.ArrayList;
15import java.util.List;
16
17import ai.nextbillion.maps.camera.CameraUpdateFactory;
18import ai.nextbillion.maps.core.MapView;
19import ai.nextbillion.maps.core.NextbillionMap;
20import ai.nextbillion.maps.core.OnMapReadyCallback;
21import ai.nextbillion.maps.location.LocationComponent;
22import ai.nextbillion.maps.location.LocationComponentActivationOptions;
23import ai.nextbillion.maps.location.LocationComponentOptions;
24import ai.nextbillion.maps.location.OnCameraTrackingChangedListener;
25import ai.nextbillion.maps.location.OnLocationCameraTransitionListener;
26import ai.nextbillion.maps.location.OnLocationClickListener;
27import ai.nextbillion.maps.location.engine.LocationEngineRequest;
28import ai.nextbillion.maps.location.modes.CameraMode;
29import ai.nextbillion.maps.location.modes.RenderMode;
30import ai.nextbillion.maps.location.permissions.PermissionsListener;
31import ai.nextbillion.maps.location.permissions.PermissionsManager;
32import androidx.annotation.NonNull;
33import androidx.appcompat.app.AppCompatActivity;
34import androidx.appcompat.widget.ListPopupWindow;
35
36public class LocationModesActivity extends AppCompatActivity implements OnMapReadyCallback,
37        OnLocationClickListener, OnCameraTrackingChangedListener {
38
39    private MapView mapView;
40    private Button locationModeBtn;
41    private Button locationTrackingBtn;
42    private View protectedGestureArea;
43
44    private PermissionsManager permissionsManager;
45
46    private LocationComponent locationComponent;
47    private NextbillionMap nextbillionMap;
48    private boolean defaultStyle = false;
49
50    private static final String SAVED_STATE_CAMERA = "saved_state_camera";
51    private static final String SAVED_STATE_RENDER = "saved_state_render";
52    private static final String SAVED_STATE_LOCATION = "saved_state_location";
53
54    @CameraMode.Mode
55    private int cameraMode = CameraMode.TRACKING;
56
57    @RenderMode.Mode
58    private int renderMode = RenderMode.NORMAL;
59
60    private Location lastLocation;
61
62    @Override
63    protected void onCreate(Bundle savedInstanceState) {
64        super.onCreate(savedInstanceState);
65        setContentView(R.layout.activity_location_modes);
66
67        mapView = findViewById(R.id.mapView);
68        protectedGestureArea = findViewById(R.id.view_protected_gesture_area);
69
70        locationModeBtn = findViewById(R.id.button_location_mode);
71        locationModeBtn.setOnClickListener(v -> {
72            if (locationComponent == null) {
73                return;
74            }
75            showModeListDialog();
76        });
77
78        locationTrackingBtn = findViewById(R.id.button_location_tracking);
79        locationTrackingBtn.setOnClickListener(v -> {
80            if (locationComponent == null) {
81                return;
82            }
83            showTrackingListDialog();
84        });
85
86
87        if (savedInstanceState != null) {
88            cameraMode = savedInstanceState.getInt(SAVED_STATE_CAMERA);
89            renderMode = savedInstanceState.getInt(SAVED_STATE_RENDER);
90            lastLocation = savedInstanceState.getParcelable(SAVED_STATE_LOCATION);
91        }
92
93        mapView.onCreate(savedInstanceState);
94
95        if (PermissionsManager.areLocationPermissionsGranted(this)) {
96            mapView.getMapAsync(this);
97        } else {
98            permissionsManager = new PermissionsManager(new PermissionsListener() {
99                @Override
100                public void onExplanationNeeded(List<String> permissionsToExplain) {
101                    Toast.makeText(LocationModesActivity.this, "You need to accept location permissions.",
102                            Toast.LENGTH_SHORT).show();
103                }
104
105                @Override
106                public void onPermissionResult(boolean granted) {
107                    if (granted) {
108                        mapView.getMapAsync(LocationModesActivity.this);
109                    } else {
110                        finish();
111                    }
112                }
113            });
114            permissionsManager.requestLocationPermissions(this);
115        }
116    }
117
118    @Override
119    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
120        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
121        permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
122    }
123
124    @SuppressLint("MissingPermission")
125    @Override
126    public void onMapReady(@NonNull NextbillionMap nextbillionMap) {
127        this.nextbillionMap = nextbillionMap;
128        nextbillionMap.animateCamera(CameraUpdateFactory.zoomBy(13));
129        nextbillionMap.setStyle(StyleConstants.NBMAP_STREETS, style -> {
130            locationComponent = nextbillionMap.getLocationComponent();
131            locationComponent.activateLocationComponent(
132                    LocationComponentActivationOptions
133                            .builder(this, style)
134                            .useSpecializedLocationLayer(true)
135                            .useDefaultLocationEngine(true)
136                            .locationEngineRequest(new LocationEngineRequest.Builder(750)
137                                    .setFastestInterval(750)
138                                    .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
139                                    .build())
140                            .build());
141
142            locationComponent.setLocationComponentEnabled(true);
143            locationComponent.addOnLocationClickListener(this);
144            locationComponent.addOnCameraTrackingChangedListener(this);
145            locationComponent.setCameraMode(cameraMode);
146            setRendererMode(renderMode);
147            locationComponent.forceLocationUpdate(lastLocation);
148        });
149    }
150
151    @Override
152    public boolean onCreateOptionsMenu(Menu menu) {
153        getMenuInflater().inflate(R.menu.menu_location_mode, menu);
154        return true;
155    }
156
157    @SuppressLint("MissingPermission")
158    @Override
159    public boolean onOptionsItemSelected(MenuItem item) {
160        if (locationComponent == null) {
161            return super.onOptionsItemSelected(item);
162        }
163
164        int id = item.getItemId();
165        if (id == R.id.action_component_disable) {
166            locationComponent.setLocationComponentEnabled(false);
167            return true;
168        } else if (id == R.id.action_component_enabled) {
169            locationComponent.setLocationComponentEnabled(true);
170            return true;
171        } else if (id == R.id.action_gestures_management_disabled) {
172            disableGesturesManagement();
173            return true;
174        } else if (id == R.id.action_gestures_management_enabled) {
175            enableGesturesManagement();
176            return true;
177        } else if (id == R.id.action_component_throttling_enabled) {
178            locationComponent.setMaxAnimationFps(5);
179        } else if (id == R.id.action_component_throttling_disabled) {
180            locationComponent.setMaxAnimationFps(Integer.MAX_VALUE);
181        } else if (id == R.id.action_component_animate_while_tracking) {
182            locationComponent.zoomWhileTracking(17, 750, new NextbillionMap.CancelableCallback() {
183                @Override
184                public void onCancel() {
185                    // No impl
186                }
187
188                @Override
189                public void onFinish() {
190                    locationComponent.tiltWhileTracking(60);
191                }
192            });
193            if (locationComponent.getCameraMode() == CameraMode.NONE) {
194
195                Toast.makeText(this, "Not possible to animate - not tracking", Toast.LENGTH_SHORT).show();
196            }
197        }
198
199        return super.onOptionsItemSelected(item);
200    }
201
202    private void disableGesturesManagement() {
203        if (locationComponent == null) {
204            return;
205        }
206
207        protectedGestureArea.getLayoutParams().height = 0;
208        protectedGestureArea.getLayoutParams().width = 0;
209
210        LocationComponentOptions options = locationComponent
211                .getLocationComponentOptions()
212                .toBuilder()
213                .trackingGesturesManagement(false)
214                .build();
215        locationComponent.applyStyle(options);
216    }
217
218    private void enableGesturesManagement() {
219        if (locationComponent == null) {
220            return;
221        }
222
223        RectF rectF = new RectF(0f, 0f, mapView.getWidth() / 2f, mapView.getHeight() / 2f);
224        protectedGestureArea.getLayoutParams().height = (int) rectF.bottom;
225        protectedGestureArea.getLayoutParams().width = (int) rectF.right;
226
227        LocationComponentOptions options = locationComponent
228                .getLocationComponentOptions()
229                .toBuilder()
230                .trackingGesturesManagement(true)
231                .trackingMultiFingerProtectedMoveArea(rectF)
232                .trackingMultiFingerMoveThreshold(500)
233                .build();
234        locationComponent.applyStyle(options);
235    }
236
237    @Override
238    protected void onStart() {
239        super.onStart();
240        mapView.onStart();
241    }
242
243    @Override
244    protected void onResume() {
245        super.onResume();
246        mapView.onResume();
247    }
248
249    @Override
250    protected void onPause() {
251        super.onPause();
252        mapView.onPause();
253    }
254
255    @Override
256    protected void onStop() {
257        super.onStop();
258        mapView.onStop();
259    }
260
261    @SuppressLint("MissingPermission")
262    @Override
263    protected void onSaveInstanceState(Bundle outState) {
264        super.onSaveInstanceState(outState);
265        mapView.onSaveInstanceState(outState);
266        outState.putInt(SAVED_STATE_CAMERA, cameraMode);
267        outState.putInt(SAVED_STATE_RENDER, renderMode);
268        if (locationComponent != null) {
269            outState.putParcelable(SAVED_STATE_LOCATION, locationComponent.getLastKnownLocation());
270        }
271    }
272
273    @Override
274    protected void onDestroy() {
275        super.onDestroy();
276        mapView.onDestroy();
277    }
278
279    @Override
280    public void onLowMemory() {
281        super.onLowMemory();
282        mapView.onLowMemory();
283    }
284
285    @Override
286    public void onLocationComponentClick() {
287        Toast.makeText(this, "OnLocationComponentClick", Toast.LENGTH_LONG).show();
288    }
289
290    private void showModeListDialog() {
291        List<String> modes = new ArrayList<>();
292        modes.add("Normal");
293        modes.add("Compass");
294        modes.add("GPS");
295        ArrayAdapter<String> profileAdapter = new ArrayAdapter<>(this,
296                android.R.layout.simple_list_item_1, modes);
297        ListPopupWindow listPopup = new ListPopupWindow(this);
298        listPopup.setAdapter(profileAdapter);
299        listPopup.setAnchorView(locationModeBtn);
300        listPopup.setOnItemClickListener((parent, itemView, position, id) -> {
301            String selectedMode = modes.get(position);
302            locationModeBtn.setText(selectedMode);
303            if (selectedMode.contentEquals("Normal")) {
304                setRendererMode(RenderMode.NORMAL);
305            } else if (selectedMode.contentEquals("Compass")) {
306                setRendererMode(RenderMode.COMPASS);
307            } else if (selectedMode.contentEquals("GPS")) {
308                setRendererMode(RenderMode.GPS);
309            }
310            listPopup.dismiss();
311        });
312        listPopup.show();
313    }
314
315    private void setRendererMode(@RenderMode.Mode int mode) {
316        renderMode = mode;
317        locationComponent.setRenderMode(mode);
318        if (mode == RenderMode.NORMAL) {
319            locationModeBtn.setText("Normal");
320        } else if (mode == RenderMode.COMPASS) {
321            locationModeBtn.setText("Compass");
322        } else if (mode == RenderMode.GPS) {
323            locationModeBtn.setText("Gps");
324        }
325    }
326
327    private void showTrackingListDialog() {
328        List<String> trackingTypes = new ArrayList<>();
329        trackingTypes.add("None");
330        trackingTypes.add("None Compass");
331        trackingTypes.add("None GPS");
332        trackingTypes.add("Tracking");
333        trackingTypes.add("Tracking Compass");
334        trackingTypes.add("Tracking GPS");
335        trackingTypes.add("Tracking GPS North");
336        ArrayAdapter<String> profileAdapter = new ArrayAdapter<>(this,
337                android.R.layout.simple_list_item_1, trackingTypes);
338        ListPopupWindow listPopup = new ListPopupWindow(this);
339        listPopup.setAdapter(profileAdapter);
340        listPopup.setAnchorView(locationTrackingBtn);
341        listPopup.setOnItemClickListener((parent, itemView, position, id) -> {
342            String selectedTrackingType = trackingTypes.get(position);
343            locationTrackingBtn.setText(selectedTrackingType);
344            if (selectedTrackingType.contentEquals("None")) {
345                setCameraTrackingMode(CameraMode.NONE);
346            } else if (selectedTrackingType.contentEquals("None Compass")) {
347                setCameraTrackingMode(CameraMode.NONE_COMPASS);
348            } else if (selectedTrackingType.contentEquals("None GPS")) {
349                setCameraTrackingMode(CameraMode.NONE_GPS);
350            } else if (selectedTrackingType.contentEquals("Tracking")) {
351                setCameraTrackingMode(CameraMode.TRACKING);
352            } else if (selectedTrackingType.contentEquals("Tracking Compass")) {
353                setCameraTrackingMode(CameraMode.TRACKING_COMPASS);
354            } else if (selectedTrackingType.contentEquals("Tracking GPS")) {
355                setCameraTrackingMode(CameraMode.TRACKING_GPS);
356            } else if (selectedTrackingType.contentEquals("Tracking GPS North")) {
357                setCameraTrackingMode(CameraMode.TRACKING_GPS_NORTH);
358            }
359            listPopup.dismiss();
360        });
361        listPopup.show();
362    }
363
364    private void setCameraTrackingMode(@CameraMode.Mode int mode) {
365        locationComponent.setCameraMode(mode, 1200, 16.0, null, 45.0,
366                new OnLocationCameraTransitionListener() {
367                    @Override
368                    public void onLocationCameraTransitionFinished(@CameraMode.Mode int cameraMode) {
369                        Toast.makeText(LocationModesActivity.this, "Transition finished", Toast.LENGTH_SHORT).show();
370                    }
371
372                    @Override
373                    public void onLocationCameraTransitionCanceled(@CameraMode.Mode int cameraMode) {
374                        Toast.makeText(LocationModesActivity.this, "Transition canceled", Toast.LENGTH_SHORT).show();
375                    }
376                });
377    }
378
379    @Override
380    public void onCameraTrackingDismissed() {
381        locationTrackingBtn.setText("None");
382    }
383
384    @Override
385    public void onCameraTrackingChanged(int currentMode) {
386        this.cameraMode = currentMode;
387        if (currentMode == CameraMode.NONE) {
388            locationTrackingBtn.setText("None");
389        } else if (currentMode == CameraMode.NONE_COMPASS) {
390            locationTrackingBtn.setText("None Compass");
391        } else if (currentMode == CameraMode.NONE_GPS) {
392            locationTrackingBtn.setText("None GPS");
393        } else if (currentMode == CameraMode.TRACKING) {
394            locationTrackingBtn.setText("Tracking");
395        } else if (currentMode == CameraMode.TRACKING_COMPASS) {
396            locationTrackingBtn.setText("Tracking Compass");
397        } else if (currentMode == CameraMode.TRACKING_GPS) {
398            locationTrackingBtn.setText("Tracking GPS");
399        } else if (currentMode == CameraMode.TRACKING_GPS_NORTH) {
400            locationTrackingBtn.setText("Tracking GPS North");
401        }
402    }
403}

Summary: The given code is an Android activity that demonstrates various location modes and features using the NextbillionMap library. It initializes a map view, handles location permissions, tracks the current location, switches between location component render modes and tracking camera modes and enables or disables the location component.

initMapView:

  1. The map view is initialized in the onCreate method by finding the view with the ID R.id.mapView. This method sets up the map view and initializes other UI elements and variables.

Location Permissions Handling:

  1. The code checks if location permissions are granted using PermissionsManager.areLocationPermissionsGranted(this). If permissions are granted, the map is asynchronously loaded using mapView.getMapAsync(this). If permissions are not granted, a PermissionsManager is created and used to request location permissions. The result of the permission request is handled in the onPermissionResult method.

Tracking Current Location Automatically when MapReady:

  1. When the map is ready (onMapReady), the NextbillionMap instance is obtained. The map's style is set, and the location component is activated with various options, including a specialized location layer, default location engine, and location update interval. The location component is enabled and configured with listeners for location clicks and camera tracking changes. The last known location is also updated.

Switch Location component RenderMode:

  1. The render mode can be switched using the showModeListDialog method, which displays a dialog with options for Normal, Compass, and GPS render modes. The selected mode is applied to the location component using setRendererMode().

Switch Location Tracking CameraMode:

  1. The camera tracking mode can be switched using the showTrackingListDialog method, which displays a dialog with options for different camera tracking modes. The selected mode is applied to the location component using setCameraTrackingMode().

Enable/Disable Location Component:

  1. The location component can be enabled or disabled by clicking on the corresponding menu items in the options menu. The status of the location component is updated accordingly using setLocationComponentEnabled.

The code also includes various lifecycle methods for managing the map view, saving and restoring the state of the activity, and handling user interactions with the location component, such as clicking and dismissing camera tracking.

Overall, the code demonstrates how to use the NextbillionMap library to implement location-based features in an Android application, including handling permissions, tracking the user's location, and customizing the render and camera tracking modes of the location component.

没找到你要找的内容?