Skip to content

Commit fc5259c

Browse files
zugaldiaCameron Mace
authored andcommitted
[WIP] Add sample activity implementing Navigation SDK (mapbox#379)
* added navigation activity * worked on locationengine * finished navigation example * added default clause (checkstyle issue)
1 parent c41741b commit fc5259c

9 files changed

Lines changed: 690 additions & 9 deletions

File tree

mapbox/app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@
155155
android:name="android.support.PARENT_ACTIVITY"
156156
android:value=".MainActivity"/>
157157
</activity>
158+
<activity
159+
android:name=".nav.NavigationActivity"
160+
android:label="@string/title_navigation">
161+
<meta-data
162+
android:name="android.support.PARENT_ACTIVITY"
163+
android:value=".MainActivity"/>
164+
</activity>
158165

159166
<!--
160167
Service to asynchronously fetch a location address using a Geocoder. Setting the

mapbox/app/src/main/java/com/mapbox/services/android/testapp/MainActivity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.mapbox.services.android.testapp.geocoding.GeocodingServiceActivity;
2424
import com.mapbox.services.android.testapp.geocoding.GeocodingWidgetActivity;
2525
import com.mapbox.services.android.testapp.location.LocationEngineActivity;
26+
import com.mapbox.services.android.testapp.nav.NavigationActivity;
2627
import com.mapbox.services.android.testapp.nav.OffRouteDetectionActivity;
2728
import com.mapbox.services.android.testapp.nav.SnapToRouteActivity;
2829
import com.mapbox.services.android.testapp.staticimage.StaticImageActivity;
@@ -145,6 +146,11 @@ protected void onCreate(Bundle savedInstanceState) {
145146
getString(R.string.title_snap_to_route),
146147
getString(R.string.description_snap_to_route),
147148
SnapToRouteActivity.class
149+
),
150+
new SampleItem(
151+
getString(R.string.title_navigation),
152+
getString(R.string.description_navigation),
153+
NavigationActivity.class
148154
)
149155
));
150156

Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
package com.mapbox.services.android.testapp.distance;
2+
3+
import android.graphics.Color;
4+
import android.graphics.PointF;
5+
import android.os.Bundle;
6+
import android.support.annotation.NonNull;
7+
import android.support.v7.app.AppCompatActivity;
8+
import android.util.Log;
9+
10+
import com.google.gson.JsonObject;
11+
import com.mapbox.mapboxsdk.geometry.LatLng;
12+
import com.mapbox.mapboxsdk.maps.MapView;
13+
import com.mapbox.mapboxsdk.maps.MapboxMap;
14+
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
15+
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
16+
import com.mapbox.mapboxsdk.style.layers.Property;
17+
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
18+
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
19+
import com.mapbox.mapboxsdk.style.sources.Source;
20+
import com.mapbox.services.android.testapp.R;
21+
import com.mapbox.services.android.testapp.Utils;
22+
import com.mapbox.services.api.ServicesException;
23+
import com.mapbox.services.api.directions.v5.DirectionsCriteria;
24+
import com.mapbox.services.api.distance.v1.MapboxDistance;
25+
import com.mapbox.services.api.distance.v1.models.DistanceResponse;
26+
import com.mapbox.services.commons.geojson.Feature;
27+
import com.mapbox.services.commons.geojson.FeatureCollection;
28+
import com.mapbox.services.commons.geojson.Point;
29+
import com.mapbox.services.commons.models.Position;
30+
31+
import java.util.ArrayList;
32+
import java.util.List;
33+
34+
import retrofit2.Call;
35+
import retrofit2.Callback;
36+
import retrofit2.Response;
37+
38+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
39+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
40+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAnchor;
41+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
42+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textFont;
43+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloColor;
44+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloWidth;
45+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textIgnorePlacement;
46+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textMaxWidth;
47+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textPadding;
48+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
49+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTranslate;
50+
51+
public class DistanceActivity extends AppCompatActivity implements OnMapReadyCallback, MapboxMap.OnMapClickListener {
52+
53+
private static final String TAG = "DistanceActivity";
54+
private static final String KEY_DURATION = "duration";
55+
private static final String KEY_NAME = "name";
56+
57+
private MapView mapView;
58+
private MapboxMap mapboxMap;
59+
private final List<Position> coordinates = new ArrayList<>();
60+
private final List<Feature> restaurants = new ArrayList<>();
61+
62+
private final List<Feature> features = new ArrayList<>();
63+
64+
@Override
65+
protected void onCreate(Bundle savedInstanceState) {
66+
super.onCreate(savedInstanceState);
67+
setContentView(R.layout.activity_distance);
68+
69+
addRestaurants();
70+
71+
for (int i = 0; i < restaurants.size(); i++) {
72+
coordinates.add((Position) restaurants.get(i).getGeometry().getCoordinates());
73+
}
74+
75+
mapView = (MapView) findViewById(R.id.mapview);
76+
mapView.onCreate(savedInstanceState);
77+
mapView.getMapAsync(this);
78+
}
79+
80+
@Override
81+
public void onMapReady(MapboxMap mapboxMap) {
82+
this.mapboxMap = mapboxMap;
83+
mapboxMap.setOnMapClickListener(this);
84+
85+
for (int i = 0; i < restaurants.size(); i++) {
86+
FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] {restaurants.get(i)});
87+
Source geoJsonSource = new GeoJsonSource(
88+
restaurants.get(i).getStringProperty(KEY_NAME) + "-source", featureCollection
89+
);
90+
mapboxMap.addSource(geoJsonSource);
91+
}
92+
93+
addMarkers();
94+
updateLayers();
95+
}
96+
97+
@Override
98+
public void onMapClick(@NonNull LatLng point) {
99+
100+
features.clear();
101+
102+
final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
103+
for (int i = 0; i < restaurants.size(); i++) {
104+
features.addAll(mapboxMap.queryRenderedFeatures(
105+
pixel,
106+
restaurants.get(i).getStringProperty(KEY_NAME) + "-layer"
107+
));
108+
}
109+
110+
features.addAll(mapboxMap.queryRenderedFeatures(pixel, "circle-layer"));
111+
112+
if (features.size() > 0) {
113+
callDistanceApi();
114+
}
115+
}
116+
117+
private void callDistanceApi() {
118+
119+
try {
120+
MapboxDistance client = new MapboxDistance.Builder()
121+
.setAccessToken(Utils.getMapboxAccessToken(DistanceActivity.this))
122+
.setCoordinates(coordinates)
123+
.setProfile(DirectionsCriteria.PROFILE_WALKING)
124+
.build();
125+
126+
client.enqueueCall(new Callback<DistanceResponse>() {
127+
@Override
128+
public void onResponse(Call<DistanceResponse> call, Response<DistanceResponse> response) {
129+
130+
// Check that the distance API response is "OK".
131+
if (response.code() == 200) {
132+
133+
if (restaurants.size() <= 0) {
134+
return;
135+
}
136+
137+
int feature = 0;
138+
for (int i = 0; i < restaurants.size(); i++) {
139+
if (restaurants.get(i).getProperty(KEY_NAME).getAsString().equals(
140+
features.get(0).getStringProperty(KEY_NAME))) {
141+
feature = i;
142+
}
143+
}
144+
145+
for (int i = 0; i < restaurants.size(); i++) {
146+
// Get the json object and replace the duration property with the updated time. We convert the API's
147+
// second value to minutes.
148+
JsonObject jsonObject = restaurants.get(i).getProperties().getAsJsonObject();
149+
jsonObject.addProperty(KEY_DURATION, (response.body().getDurations()[feature][i] / 60));
150+
151+
// It is necessary to update the geojson source now along with the layers.
152+
FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] {restaurants.get(i)});
153+
GeoJsonSource source = mapboxMap.getSourceAs(restaurants.get(i).getStringProperty(KEY_NAME) + "-source");
154+
if (source != null) {
155+
source.setGeoJson(featureCollection);
156+
}
157+
}
158+
updateLayers();
159+
}
160+
}
161+
162+
@Override
163+
public void onFailure(Call<DistanceResponse> call, Throwable throwable) {
164+
Log.e(TAG, "MapboxDistance error: " + throwable.getMessage());
165+
}
166+
});
167+
168+
169+
} catch (ServicesException servicesException) {
170+
Log.e(TAG, "MapboxDistance error: " + servicesException.getMessage());
171+
servicesException.printStackTrace();
172+
}
173+
174+
}
175+
176+
private void addMarkers() {
177+
for (int i = 0; i < restaurants.size(); i++) {
178+
CircleLayer circleLayer = new CircleLayer(
179+
restaurants.get(i).getStringProperty("name") + "-circle-layer",
180+
restaurants.get(i).getStringProperty("name") + "-source"
181+
).withProperties(
182+
circleColor(Color.parseColor("#e55e5e")),
183+
circleRadius(10f)
184+
);
185+
186+
mapboxMap.addLayer(circleLayer);
187+
188+
SymbolLayer nameLayer = new SymbolLayer(
189+
restaurants.get(i).getStringProperty("name") + "-layer-name",
190+
restaurants.get(i).getStringProperty("name") + "-source"
191+
).withProperties(
192+
textSize(14f),
193+
textFont(new String[] {"Open Sans Bold", "Arial Unicode MS Bold"}),
194+
textHaloColor(Color.WHITE),
195+
textHaloWidth(0.75f),
196+
textIgnorePlacement(true),
197+
textPadding(0f),
198+
textTranslate(new Float[] {14f, 0f}),
199+
textAnchor(Property.TEXT_ANCHOR_BOTTOM_LEFT),
200+
textField(restaurants.get(i).getStringProperty("name")),
201+
textMaxWidth(8f)
202+
);
203+
mapboxMap.addLayer(nameLayer);
204+
}
205+
}
206+
207+
private void updateLayers() {
208+
209+
for (int i = 0; i < restaurants.size(); i++) {
210+
if (restaurants.get(i).hasProperty("name" + "-layer")
211+
&& mapboxMap.getLayer(restaurants.get(i).getStringProperty("name" + "-layer")) != null) {
212+
mapboxMap.removeLayer(restaurants.get(i).getStringProperty("name") + "-layer");
213+
}
214+
SymbolLayer marker = new SymbolLayer(
215+
restaurants.get(i).getStringProperty("name") + "-layer",
216+
restaurants.get(i).getStringProperty("name") + "-source"
217+
).withProperties(
218+
textSize(12f),
219+
textHaloColor(Color.WHITE),
220+
textTranslate(new Float[] {14f, 0f}),
221+
textHaloWidth(0.75f),
222+
textIgnorePlacement(true),
223+
textPadding(0f),
224+
textAnchor(Property.TEXT_ANCHOR_TOP_LEFT),
225+
textField("{duration}" + " min"),
226+
textMaxWidth(8f)
227+
);
228+
mapboxMap.addLayer(marker);
229+
}
230+
}
231+
232+
@Override
233+
protected void onStart() {
234+
super.onStart();
235+
mapView.onStart();
236+
}
237+
238+
@Override
239+
public void onResume() {
240+
super.onResume();
241+
mapView.onResume();
242+
}
243+
244+
@Override
245+
public void onPause() {
246+
super.onPause();
247+
mapView.onPause();
248+
}
249+
250+
@Override
251+
public void onLowMemory() {
252+
super.onLowMemory();
253+
mapView.onLowMemory();
254+
}
255+
256+
@Override
257+
protected void onStop() {
258+
super.onStop();
259+
mapView.onStop();
260+
}
261+
262+
@Override
263+
protected void onDestroy() {
264+
super.onDestroy();
265+
mapView.onDestroy();
266+
}
267+
268+
@Override
269+
protected void onSaveInstanceState(Bundle outState) {
270+
super.onSaveInstanceState(outState);
271+
mapView.onSaveInstanceState(outState);
272+
}
273+
274+
private void addRestaurants() {
275+
276+
Feature franklinBarbecue = Feature.fromGeometry(
277+
Point.fromCoordinates(Position.fromCoordinates(-97.731250, 30.270168))
278+
);
279+
franklinBarbecue.addStringProperty(KEY_NAME, "Franklin Barbecue");
280+
franklinBarbecue.addNumberProperty(KEY_DURATION, 0);
281+
restaurants.add(franklinBarbecue); // Franklin Barbecue
282+
283+
Feature lamberts = Feature.fromGeometry(
284+
Point.fromCoordinates(Position.fromCoordinates(-97.747905, 30.265222))
285+
);
286+
lamberts.addStringProperty(KEY_NAME, "Lamberts");
287+
lamberts.addNumberProperty(KEY_DURATION, 0);
288+
restaurants.add(lamberts); // Lamberts
289+
290+
Feature stubbsBarbq = Feature.fromGeometry(
291+
Point.fromCoordinates(Position.fromCoordinates(-97.736278, 30.268506))
292+
);
293+
stubbsBarbq.addStringProperty(KEY_NAME, "Stubb's Bar-B-Q");
294+
stubbsBarbq.addNumberProperty(KEY_DURATION, 0);
295+
restaurants.add(stubbsBarbq); // Stubb's Bar-B-Q
296+
297+
Feature stilesSwitch = Feature.fromGeometry(
298+
Point.fromCoordinates(Position.fromCoordinates(-97.721459, 30.334567))
299+
);
300+
stilesSwitch.addStringProperty(KEY_NAME, "Stiles Switch");
301+
stilesSwitch.addNumberProperty(KEY_DURATION, 0);
302+
restaurants.add(stilesSwitch); // Stiles Switch
303+
304+
Feature laBarbecue = Feature.fromGeometry(
305+
Point.fromCoordinates(Position.fromCoordinates(-97.724013, 30.257052))
306+
);
307+
laBarbecue.addStringProperty(KEY_NAME, "La Barbecue");
308+
laBarbecue.addNumberProperty(KEY_DURATION, 0);
309+
restaurants.add(laBarbecue); // La Barbecue
310+
311+
Feature freedmens = Feature.fromGeometry(
312+
Point.fromCoordinates(Position.fromCoordinates(-97.747936, 30.288418))
313+
);
314+
freedmens.addStringProperty(KEY_NAME, "Freedmen's");
315+
freedmens.addNumberProperty(KEY_DURATION, 0);
316+
restaurants.add(freedmens); // Freedmen's
317+
318+
Feature micklethwait = Feature.fromGeometry(
319+
Point.fromCoordinates(Position.fromCoordinates(-97.725124, 30.268580))
320+
);
321+
micklethwait.addStringProperty(KEY_NAME, "Micklethwait Craft Meats");
322+
micklethwait.addNumberProperty(KEY_DURATION, 0);
323+
restaurants.add(micklethwait); // Micklethwait Craft Meats
324+
325+
Feature kerlinBbq = Feature.fromGeometry(
326+
Point.fromCoordinates(Position.fromCoordinates(-97.725714, 30.257843))
327+
);
328+
kerlinBbq.addStringProperty(KEY_NAME, "Kerlin BBQ");
329+
kerlinBbq.addNumberProperty(KEY_DURATION, 0);
330+
restaurants.add(kerlinBbq); // Kerlin BBQ
331+
332+
Feature countryLine = Feature.fromGeometry(
333+
Point.fromCoordinates(Position.fromCoordinates(-97.785535, 30.357089))
334+
);
335+
countryLine.addStringProperty(KEY_NAME, "County Line");
336+
countryLine.addNumberProperty(KEY_DURATION, 0);
337+
restaurants.add(countryLine); // County Line
338+
339+
Feature ironWorksBbq = Feature.fromGeometry(
340+
Point.fromCoordinates(Position.fromCoordinates(-97.739009, 30.262272))
341+
);
342+
ironWorksBbq.addStringProperty(KEY_NAME, "Iron Works BBQ");
343+
ironWorksBbq.addNumberProperty(KEY_DURATION, 0);
344+
restaurants.add(ironWorksBbq); // Iron Works BBQ
345+
346+
Feature houseParkBarbecue = Feature.fromGeometry(
347+
Point.fromCoordinates(Position.fromCoordinates(-97.750397, 30.276797))
348+
);
349+
houseParkBarbecue.addStringProperty(KEY_NAME, "House Park Barbecue");
350+
houseParkBarbecue.addNumberProperty(KEY_DURATION, 0);
351+
restaurants.add(houseParkBarbecue); // House Park Barbecue
352+
353+
}
354+
}

0 commit comments

Comments
 (0)