3
import android.annotation.SuppressLint;
4
import android.graphics.RectF;
5
import android.location.Location;
6
import android.os.Bundle;
7
import android.view.Menu;
8
import android.view.MenuItem;
9
import android.view.View;
10
import android.widget.ArrayAdapter;
11
import android.widget.Button;
12
import android.widget.Toast;
14
import java.util.ArrayList;
17
import ai.nextbillion.maps.camera.CameraUpdateFactory;
18
import ai.nextbillion.maps.core.MapView;
19
import ai.nextbillion.maps.core.NextbillionMap;
20
import ai.nextbillion.maps.core.OnMapReadyCallback;
21
import ai.nextbillion.maps.location.LocationComponent;
22
import ai.nextbillion.maps.location.LocationComponentActivationOptions;
23
import ai.nextbillion.maps.location.LocationComponentOptions;
24
import ai.nextbillion.maps.location.OnCameraTrackingChangedListener;
25
import ai.nextbillion.maps.location.OnLocationCameraTransitionListener;
26
import ai.nextbillion.maps.location.OnLocationClickListener;
27
import ai.nextbillion.maps.location.engine.LocationEngineRequest;
28
import ai.nextbillion.maps.location.modes.CameraMode;
29
import ai.nextbillion.maps.location.modes.RenderMode;
30
import ai.nextbillion.maps.location.permissions.PermissionsListener;
31
import ai.nextbillion.maps.location.permissions.PermissionsManager;
32
import androidx.annotation.NonNull;
33
import androidx.appcompat.app.AppCompatActivity;
34
import androidx.appcompat.widget.ListPopupWindow;
36
public class LocationModesActivity extends AppCompatActivity implements OnMapReadyCallback,
37
OnLocationClickListener, OnCameraTrackingChangedListener {
39
private MapView mapView;
40
private Button locationModeBtn;
41
private Button locationTrackingBtn;
42
private View protectedGestureArea;
44
private PermissionsManager permissionsManager;
46
private LocationComponent locationComponent;
47
private NextbillionMap nextbillionMap;
48
private boolean defaultStyle = false;
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";
55
private int cameraMode = CameraMode.TRACKING;
58
private int renderMode = RenderMode.NORMAL;
60
private Location lastLocation;
63
protected void onCreate(Bundle savedInstanceState) {
64
super.onCreate(savedInstanceState);
65
setContentView(R.layout.activity_location_modes);
67
mapView = findViewById(R.id.mapView);
68
protectedGestureArea = findViewById(R.id.view_protected_gesture_area);
70
locationModeBtn = findViewById(R.id.button_location_mode);
71
locationModeBtn.setOnClickListener(v -> {
72
if (locationComponent == null) {
78
locationTrackingBtn = findViewById(R.id.button_location_tracking);
79
locationTrackingBtn.setOnClickListener(v -> {
80
if (locationComponent == null) {
83
showTrackingListDialog();
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);
93
mapView.onCreate(savedInstanceState);
95
if (PermissionsManager.areLocationPermissionsGranted(this)) {
96
mapView.getMapAsync(this);
98
permissionsManager = new PermissionsManager(new PermissionsListener() {
100
public void onExplanationNeeded(List<String> permissionsToExplain) {
101
Toast.makeText(LocationModesActivity.this, "You need to accept location permissions.",
102
Toast.LENGTH_SHORT).show();
106
public void onPermissionResult(boolean granted) {
108
mapView.getMapAsync(LocationModesActivity.this);
114
permissionsManager.requestLocationPermissions(this);
119
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
120
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
121
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
124
@SuppressLint("MissingPermission")
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)
142
locationComponent.setLocationComponentEnabled(true);
143
locationComponent.addOnLocationClickListener(this);
144
locationComponent.addOnCameraTrackingChangedListener(this);
145
locationComponent.setCameraMode(cameraMode);
146
setRendererMode(renderMode);
147
locationComponent.forceLocationUpdate(lastLocation);
152
public boolean onCreateOptionsMenu(Menu menu) {
153
getMenuInflater().inflate(R.menu.menu_location_mode, menu);
157
@SuppressLint("MissingPermission")
159
public boolean onOptionsItemSelected(MenuItem item) {
160
if (locationComponent == null) {
161
return super.onOptionsItemSelected(item);
164
int id = item.getItemId();
165
if (id == R.id.action_component_disable) {
166
locationComponent.setLocationComponentEnabled(false);
168
} else if (id == R.id.action_component_enabled) {
169
locationComponent.setLocationComponentEnabled(true);
171
} else if (id == R.id.action_gestures_management_disabled) {
172
disableGesturesManagement();
174
} else if (id == R.id.action_gestures_management_enabled) {
175
enableGesturesManagement();
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() {
184
public void onCancel() {
189
public void onFinish() {
190
locationComponent.tiltWhileTracking(60);
193
if (locationComponent.getCameraMode() == CameraMode.NONE) {
195
Toast.makeText(this, "Not possible to animate - not tracking", Toast.LENGTH_SHORT).show();
199
return super.onOptionsItemSelected(item);
202
private void disableGesturesManagement() {
203
if (locationComponent == null) {
207
protectedGestureArea.getLayoutParams().height = 0;
208
protectedGestureArea.getLayoutParams().width = 0;
210
LocationComponentOptions options = locationComponent
211
.getLocationComponentOptions()
213
.trackingGesturesManagement(false)
215
locationComponent.applyStyle(options);
218
private void enableGesturesManagement() {
219
if (locationComponent == null) {
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;
227
LocationComponentOptions options = locationComponent
228
.getLocationComponentOptions()
230
.trackingGesturesManagement(true)
231
.trackingMultiFingerProtectedMoveArea(rectF)
232
.trackingMultiFingerMoveThreshold(500)
234
locationComponent.applyStyle(options);
238
protected void onStart() {
244
protected void onResume() {
250
protected void onPause() {
256
protected void onStop() {
261
@SuppressLint("MissingPermission")
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());
274
protected void onDestroy() {
280
public void onLowMemory() {
282
mapView.onLowMemory();
286
public void onLocationComponentClick() {
287
Toast.makeText(this, "OnLocationComponentClick", Toast.LENGTH_LONG).show();
290
private void showModeListDialog() {
291
List<String> modes = new ArrayList<>();
293
modes.add("Compass");
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);
315
private void setRendererMode(@RenderMode.Mode int 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");
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);
364
private void setCameraTrackingMode(@CameraMode.Mode int mode) {
365
locationComponent.setCameraMode(mode, 1200, 16.0, null, 45.0,
366
new OnLocationCameraTransitionListener() {
368
public void onLocationCameraTransitionFinished(@CameraMode.Mode int cameraMode) {
369
Toast.makeText(LocationModesActivity.this, "Transition finished", Toast.LENGTH_SHORT).show();
373
public void onLocationCameraTransitionCanceled(@CameraMode.Mode int cameraMode) {
374
Toast.makeText(LocationModesActivity.this, "Transition canceled", Toast.LENGTH_SHORT).show();
380
public void onCameraTrackingDismissed() {
381
locationTrackingBtn.setText("None");
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");