From 68c78d5b5b886b2da9dfc45a211116e62bd17f55 Mon Sep 17 00:00:00 2001 From: danesfeder Date: Wed, 11 Oct 2017 11:15:10 -0400 Subject: Add navigation view example --- .../android/MapboxGLAndroidSDKTestApp/build.gradle | 11 + .../src/main/AndroidManifest.xml | 11 + .../testapp/activity/NavigationViewActivity.java | 317 +++++++++++++++++++++ .../activity/userlocation/MockLocationEngine.java | 5 + .../main/res/layout/activity_navigation_view.xml | 47 +++ .../src/main/res/values/descriptions.xml | 1 + platform/android/dependencies.gradle | 8 +- 7 files changed, 396 insertions(+), 4 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/NavigationViewActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_navigation_view.xml diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle index 67939b5144..2e14478fb5 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle +++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle @@ -60,6 +60,17 @@ dependencies { compile rootProject.ext.dep.supportAppcompatV7 compile rootProject.ext.dep.supportRecyclerView + // Navigation SDK UI + compile ('com.mapbox.mapboxsdk:mapbox-android-navigation-ui:0.7.0-SNAPSHOT@aar') { + transitive = true + exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-sdk' + } + + // Location Layer Plugin + compile ('com.mapbox.mapboxsdk:mapbox-android-plugin-locationlayer:0.1.0@aar') { + exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-sdk' + } + // Leak Canary debugCompile rootProject.ext.dep.leakCanaryDebug releaseCompile rootProject.ext.dep.leakCanaryRelease diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index bf97749b9e..ced18e012e 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -23,6 +23,17 @@ + + + + { + + private static final int CAMERA_ANIMATION_DURATION = 1000; + + private LocationLayerPlugin locationLayer; + private LocationEngine locationEngine; + private NavigationMapRoute mapRoute; + private MapboxMap mapboxMap; + + private MapView mapView; + private Button launchRouteBtn; + private ProgressBar loading; + private Switch demoSwitch; + + private Marker currentMarker; + private Position currentPosition; + private Position destination; + private DirectionsRoute route; + + private boolean locationFound; + private boolean shouldSimulateRoute; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_navigation_view); + bind(); + mapView.onCreate(savedInstanceState); + mapView.getMapAsync(this); + demoSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + shouldSimulateRoute = checked; + } + }); + launchRouteBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + launchNavigationWithRoute(); + } + }); + } + + private void bind() { + mapView = findViewById(R.id.mapView); + launchRouteBtn = findViewById(R.id.launchRouteBtn); + loading = findViewById(R.id.loading); + demoSwitch = findViewById(R.id.demoSwitch); + } + + @SuppressWarnings({"MissingPermission"}) + @Override + protected void onStart() { + super.onStart(); + mapView.onStart(); + if (locationLayer != null) { + locationLayer.onStart(); + } + } + + @SuppressWarnings({"MissingPermission"}) + @Override + public void onResume() { + super.onResume(); + mapView.onResume(); + if (locationEngine != null) { + locationEngine.addLocationEngineListener(this); + if (!locationEngine.isConnected()) { + locationEngine.activate(); + } + } + } + + @Override + public void onPause() { + super.onPause(); + mapView.onPause(); + if (locationEngine != null) { + locationEngine.removeLocationEngineListener(this); + } + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } + + @Override + protected void onStop() { + super.onStop(); + mapView.onStop(); + if (locationLayer != null) { + locationLayer.onStop(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + if (locationEngine != null) { + locationEngine.removeLocationUpdates(); + locationEngine.deactivate(); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + @Override + public void onMapReady(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + this.mapboxMap.setOnMapLongClickListener(this); + initLocationEngine(); + initLocationLayer(); + initMapRoute(); + } + + @Override + public void onMapLongClick(@NonNull LatLng point) { + destination = Position.fromCoordinates(point.getLongitude(), point.getLatitude()); + launchRouteBtn.setEnabled(false); + loading.setVisibility(View.VISIBLE); + setCurrentMarkerPosition(point); + if (currentPosition != null) { + fetchRoute(); + } + } + + @SuppressWarnings({"MissingPermission"}) + @Override + public void onConnected() { + locationEngine.requestLocationUpdates(); + } + + @Override + public void onLocationChanged(Location location) { + currentPosition = Position.fromCoordinates(location.getLongitude(), location.getLatitude()); + onLocationFound(location); + } + + @Override + public void onResponse(Call call, Response response) { + if (validRouteResponse(response)) { + route = response.body().getRoutes().get(0); + launchRouteBtn.setEnabled(true); + mapRoute.addRoute(route); + boundCameraToRoute(); + hideLoading(); + } + } + + @Override + public void onFailure(Call call, Throwable throwable) { + Timber.e(throwable.getMessage()); + } + + @SuppressWarnings({"MissingPermission"}) + private void initLocationEngine() { + locationEngine = new LocationSource(this); + locationEngine.setPriority(HIGH_ACCURACY); + locationEngine.setInterval(0); + locationEngine.setFastestInterval(1000); + locationEngine.addLocationEngineListener(this); + locationEngine.activate(); + + if (locationEngine.getLastLocation() != null) { + Location lastLocation = locationEngine.getLastLocation(); + currentPosition = Position.fromCoordinates(lastLocation.getLongitude(), lastLocation.getLatitude()); + } + } + + @SuppressWarnings({"MissingPermission"}) + private void initLocationLayer() { + locationLayer = new LocationLayerPlugin(mapView, mapboxMap, locationEngine); + locationLayer.setLocationLayerEnabled(LocationLayerMode.COMPASS); + } + + private void initMapRoute() { + mapRoute = new NavigationMapRoute(mapView, mapboxMap); + } + + private void fetchRoute() { + NavigationRoute.builder() + .accessToken(Mapbox.getAccessToken()) + .origin(currentPosition) + .destination(destination) + .build() + .getRoute(this); + loading.setVisibility(View.VISIBLE); + } + + private void launchNavigationWithRoute() { + if (route != null) { + NavigationLauncher.startNavigation(this, route, + null, shouldSimulateRoute); + } + } + + private boolean validRouteResponse(Response response) { + return response.body() != null + && response.body().getRoutes() != null + && response.body().getRoutes().size() > 0; + } + + private void hideLoading() { + if (loading.getVisibility() == View.VISIBLE) { + loading.setVisibility(View.INVISIBLE); + } + } + + private void onLocationFound(Location location) { + if (!locationFound) { + animateCamera(new LatLng(location.getLatitude(), location.getLongitude())); + Snackbar.make(mapView, "Long press map to place waypoint", BaseTransientBottomBar.LENGTH_LONG).show(); + locationFound = true; + hideLoading(); + } + } + + public void boundCameraToRoute() { + if (route != null) { + List routeCoords = LineString.fromPolyline(route.getGeometry(), + Constants.PRECISION_6).getCoordinates(); + List bboxPoints = new ArrayList<>(); + for (Position position : routeCoords) { + bboxPoints.add(new LatLng(position.getLatitude(), position.getLongitude())); + } + if (bboxPoints.size() > 1) { + try { + LatLngBounds bounds = new LatLngBounds.Builder().includes(bboxPoints).build(); + animateCameraBbox(bounds, CAMERA_ANIMATION_DURATION, new int[] {50, 500, 50, 335}); + } catch (InvalidLatLngBoundsException exception) { + Toast.makeText(this, "Valid route not found.", Toast.LENGTH_SHORT).show(); + } + } + } + } + + private void animateCameraBbox(LatLngBounds bounds, int animationTime, int[] padding) { + mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, + padding[0], padding[1], padding[2], padding[3]), animationTime); + } + + private void animateCamera(LatLng point) { + mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(point, 16), CAMERA_ANIMATION_DURATION); + } + + private void setCurrentMarkerPosition(LatLng position) { + if (position != null) { + if (currentMarker == null) { + MarkerViewOptions markerViewOptions = new MarkerViewOptions() + .position(position); + currentMarker = mapboxMap.addMarker(markerViewOptions); + } else { + currentMarker.setPosition(position); + } + } + } +} + diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java index da3c78b07a..df52ccf727 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java @@ -87,6 +87,11 @@ public class MockLocationEngine extends LocationEngine { } } + @Override + public Type obtainType() { + return Type.MOCK; + } + private static class LocationAnimator extends AnimatorListenerAdapter { private static final long DURATION_ANIMATION = 10000; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_navigation_view.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_navigation_view.xml new file mode 100644 index 0000000000..52908d17c0 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_navigation_view.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + +