1
1
package com .mapbox .mapboxandroiddemo .examples .javaservices ;
2
2
3
3
import android .content .Context ;
4
+ import android .graphics .BitmapFactory ;
4
5
import android .os .Bundle ;
5
6
import androidx .annotation .NonNull ;
6
7
import androidx .appcompat .app .AppCompatActivity ;
33
34
import com .mapbox .mapboxsdk .maps .MapboxMap ;
34
35
import com .mapbox .mapboxsdk .maps .OnMapReadyCallback ;
35
36
import com .mapbox .mapboxsdk .maps .Style ;
37
+ import com .mapbox .mapboxsdk .style .layers .SymbolLayer ;
38
+ import com .mapbox .mapboxsdk .style .sources .GeoJsonSource ;
36
39
import com .mapbox .turf .TurfConversion ;
37
40
38
41
import java .io .InputStream ;
46
49
import retrofit2 .Response ;
47
50
import timber .log .Timber ;
48
51
52
+ import static com .mapbox .mapboxsdk .style .layers .PropertyFactory .iconAllowOverlap ;
53
+ import static com .mapbox .mapboxsdk .style .layers .PropertyFactory .iconIgnorePlacement ;
54
+ import static com .mapbox .mapboxsdk .style .layers .PropertyFactory .iconImage ;
55
+
49
56
50
57
/**
51
- * Use the Mapbox Java Services SDK's Matrix API to retrieve travel times between many points.
58
+ * Use the Mapbox Java SDK's Matrix API to retrieve travel times between many points.
52
59
*/
53
- public class MatrixApiActivity extends AppCompatActivity {
60
+ public class MatrixApiActivity extends AppCompatActivity implements MapboxMap . OnMapClickListener {
54
61
62
+ private static final String ICON_ID = "ICON_ID" ;
63
+ private static final String STATION_NAME_PROPERTY = "Station_Name" ;
64
+ private static final String SOURCE_ID = "SOURCE_ID" ;
65
+ private static final String LAYER_ID = "LAYER_ID" ;
66
+ private List <Point > pointList ;
67
+ private List <SingleRecyclerViewMatrixLocation > matrixLocationList ;
55
68
private MapView mapView ;
56
69
private MapboxMap mapboxMap ;
57
- private List <Point > pointList ;
58
70
private FeatureCollection featureCollection ;
59
- private RecyclerView recyclerView ;
60
71
private MatrixApiLocationRecyclerViewAdapter matrixApiLocationRecyclerViewAdapter ;
61
- private ArrayList <SingleRecyclerViewMatrixLocation > matrixLocationList ;
62
72
63
73
@ Override
64
74
protected void onCreate (Bundle savedInstanceState ) {
@@ -71,10 +81,8 @@ protected void onCreate(Bundle savedInstanceState) {
71
81
// This contains the MapView in XML and needs to be called after the access token is configured.
72
82
setContentView (R .layout .activity_matrix_api );
73
83
74
- recyclerView = findViewById (R .id .matrix_api_recyclerview );
75
-
76
- // Create list of positions from local GeoJSON file
77
- initPositionListFromGeoJsonFile ();
84
+ // Create a FeatureCollection via local GeoJSON file
85
+ initFeatureCollection ();
78
86
79
87
mapView = findViewById (R .id .mapView );
80
88
mapView .onCreate (savedInstanceState );
@@ -83,29 +91,33 @@ protected void onCreate(Bundle savedInstanceState) {
83
91
public void onMapReady (@ NonNull final MapboxMap mapboxMap ) {
84
92
MatrixApiActivity .this .mapboxMap = mapboxMap ;
85
93
86
- mapboxMap .setStyle (new Style .Builder ().fromUri ("mapbox://styles/mapbox/cj8gg22et19ot2rnz65958fkn" ),
94
+ mapboxMap .setStyle (new Style .Builder ().fromUri ("mapbox://styles/mapbox/cj8gg22et19ot2rnz65958fkn" )
95
+ // Add the SymbolLayer icon image to the map style
96
+ .withImage (ICON_ID , BitmapFactory .decodeResource (
97
+ MatrixApiActivity .this .getResources (), R .drawable .lightning_bolt ))
98
+
99
+ // Adding a GeoJson source for the SymbolLayer icons.
100
+ .withSource (new GeoJsonSource (SOURCE_ID , featureCollection ))
101
+
102
+ // Adding the actual SymbolLayer to the map style.
103
+ .withLayer (new SymbolLayer (LAYER_ID , SOURCE_ID )
104
+ .withProperties (
105
+ iconImage (ICON_ID ),
106
+ iconAllowOverlap (true ),
107
+ iconIgnorePlacement (true ))
108
+ ),
87
109
new Style .OnStyleLoaded () {
88
110
@ Override
89
111
public void onStyleLoaded (@ NonNull Style style ) {
90
- // Add markers to the map
91
- addMarkers ();
92
112
93
113
// Set up list of locations to pass to the recyclerview
94
114
initMatrixLocationListForRecyclerView ();
95
115
96
116
// Set up the recyclerview of charging station cards
97
117
initRecyclerView ();
98
118
99
- mapboxMap .setOnMarkerClickListener (new MapboxMap .OnMarkerClickListener () {
100
- @ Override
101
- public boolean onMarkerClick (@ NonNull Marker marker ) {
119
+ mapboxMap .addOnMapClickListener (MatrixApiActivity .this );
102
120
103
- // Make a call to the Mapbox Matrix API
104
- makeMapboxMatrixApiCall (getClickedMarkerNumInPositionList (marker ), Point .fromLngLat (
105
- marker .getPosition ().getLongitude (), marker .getPosition ().getLatitude ()));
106
- return false ;
107
- }
108
- });
109
121
Toast .makeText (MatrixApiActivity .this , R .string .click_on_marker_instruction_toast ,
110
122
Toast .LENGTH_SHORT ).show ();
111
123
}
@@ -114,23 +126,51 @@ public boolean onMarkerClick(@NonNull Marker marker) {
114
126
});
115
127
}
116
128
117
- private int getClickedMarkerNumInPositionList (Marker clickedMarker ) {
118
- int clickedMarkerIndexPositionInList = -1 ;
119
- if (clickedMarker != null ) {
120
- for (Marker singleMarker : mapboxMap .getMarkers ()) {
121
- if (singleMarker == clickedMarker ) {
122
- clickedMarkerIndexPositionInList = mapboxMap .getMarkers ().indexOf (singleMarker );
129
+ @ Override
130
+ public boolean onMapClick (@ NonNull LatLng point ) {
131
+ List <Feature > renderedStationFeatures = mapboxMap .queryRenderedFeatures (
132
+ mapboxMap .getProjection ().toScreenLocation (point ), LAYER_ID );
133
+ if (!renderedStationFeatures .isEmpty ()) {
134
+ Point pointOfSelectedStation = (Point ) renderedStationFeatures .get (0 ).geometry ();
135
+ if (pointOfSelectedStation != null ) {
136
+ String selectedBoltFeatureName = renderedStationFeatures .get (0 ).getStringProperty (STATION_NAME_PROPERTY );
137
+ List <Feature > featureList = featureCollection .features ();
138
+ for (int i = 0 ; i < featureList .size (); i ++) {
139
+ if (featureList .get (i ).getStringProperty (STATION_NAME_PROPERTY ).equals (selectedBoltFeatureName )) {
140
+ makeMapboxMatrixApiCall (i );
141
+ }
123
142
}
124
143
}
125
- return clickedMarkerIndexPositionInList ;
126
- } else {
127
- return 0 ;
128
144
}
145
+ return true ;
129
146
}
130
147
148
+ /**
149
+ * Create a {@link FeatureCollection} from a locally stored asset file.
150
+ */
151
+ private void initFeatureCollection () {
152
+ // Get GeoJSON features from GeoJSON file in the assets folder
153
+ featureCollection = FeatureCollection .fromJson (loadGeoJsonFromAsset ("boston_charge_stations.geojson" ));
154
+
155
+ // Initialize List<Position> for eventual use in the Matrix API call
156
+ pointList = new ArrayList <>();
157
+
158
+ // Get the position of each GeoJSON feature and build the list of Position
159
+ // objects for eventual use in the Matrix API call
160
+ if (featureCollection != null && featureCollection .features () != null ) {
161
+ for (Feature singleLocation : featureCollection .features ()) {
162
+ pointList .add ((Point ) singleLocation .geometry ());
163
+ }
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Set up the RecyclerView, which will display the travel distances to each charge station.
169
+ */
131
170
private void initRecyclerView () {
132
171
matrixApiLocationRecyclerViewAdapter = new MatrixApiLocationRecyclerViewAdapter (this ,
133
172
matrixLocationList );
173
+ RecyclerView recyclerView = findViewById (R .id .matrix_api_recyclerview );
134
174
recyclerView .setLayoutManager (new LinearLayoutManager (getApplicationContext (),
135
175
LinearLayoutManager .HORIZONTAL , true ));
136
176
recyclerView .setItemAnimator (new DefaultItemAnimator ());
@@ -139,7 +179,12 @@ private void initRecyclerView() {
139
179
snapHelper .attachToRecyclerView (recyclerView );
140
180
}
141
181
142
- private void makeMapboxMatrixApiCall (final int markerPositionInList , Point pointOfClickedMarker ) {
182
+ /**
183
+ * Make a call to the Mapbox Matrix API to get the travel distances to each charge station.
184
+ *
185
+ * @param markerPositionInList the position of the tapped bolt icon {@link Feature} in the FeatureCollection.
186
+ */
187
+ private void makeMapboxMatrixApiCall (final int markerPositionInList ) {
143
188
144
189
// Build Mapbox Matrix API parameters
145
190
MapboxMatrix directionsMatrixClient = MapboxMatrix .builder ()
@@ -157,15 +202,12 @@ public void onResponse(Call<MatrixResponse> call,
157
202
List <Double []> durationsToAllOfTheLocationsFromTheOrigin = response .body ().durations ();
158
203
if (durationsToAllOfTheLocationsFromTheOrigin != null ) {
159
204
for (int x = 0 ; x < durationsToAllOfTheLocationsFromTheOrigin .size (); x ++) {
160
- String finalConvertedFormattedDistance = String .valueOf (new DecimalFormat ("#.##" )
161
- . format ( TurfConversion .convertLength (
205
+ String finalConvertedFormattedDistance = String .valueOf (new DecimalFormat ("#.##" ). format (
206
+ TurfConversion .convertLength (
162
207
durationsToAllOfTheLocationsFromTheOrigin .get (markerPositionInList )[x ],
163
208
"meters" , "miles" )));
164
- if (x == markerPositionInList ) {
165
- matrixLocationList .get (x ).setDistanceFromOrigin (finalConvertedFormattedDistance );
166
- }
209
+ matrixLocationList .get (x ).setDistanceFromOrigin (finalConvertedFormattedDistance );
167
210
if (x != markerPositionInList ) {
168
- matrixLocationList .get (x ).setDistanceFromOrigin (finalConvertedFormattedDistance );
169
211
matrixApiLocationRecyclerViewAdapter .notifyDataSetChanged ();
170
212
}
171
213
}
@@ -177,7 +219,7 @@ public void onResponse(Call<MatrixResponse> call,
177
219
public void onFailure (Call <MatrixResponse > call , Throwable throwable ) {
178
220
Toast .makeText (MatrixApiActivity .this , R .string .call_error ,
179
221
Toast .LENGTH_SHORT ).show ();
180
- Timber .d ( "onResponse onFailure" );
222
+ Timber .d ("onResponse onFailure" );
181
223
}
182
224
});
183
225
}
@@ -204,40 +246,23 @@ private String loadGeoJsonFromAsset(String filename) {
204
246
byte [] buffer = new byte [size ];
205
247
is .read (buffer );
206
248
is .close ();
207
- return new String (buffer , Charset .forName ("UTF-8" ));
249
+ return new String (buffer , Charset .forName ("UTF-8" ));
208
250
} catch (Exception exception ) {
209
251
Timber .d (exception .toString (), "Exception Loading GeoJSON: " );
210
252
exception .printStackTrace ();
211
253
return null ;
212
254
}
213
255
}
214
256
215
- private void initPositionListFromGeoJsonFile () {
216
-
217
- // Get GeoJSON features from GeoJSON file in the assets folder
218
- featureCollection = FeatureCollection .fromJson (loadGeoJsonFromAsset ("boston_charge_stations.geojson" ));
219
-
220
- // Initialize List<Position> for eventual use in the Matrix API call
221
- pointList = new ArrayList <>();
222
-
223
- // Get the position of each GeoJSON feature and build the list of Position
224
- // objects for eventual use in the Matrix API call
225
- if (featureCollection .features () != null ) {
226
- for (Feature singleLocation : featureCollection .features ()) {
227
- pointList .add ((Point ) singleLocation .geometry ());
228
- }
229
- }
230
- }
231
-
257
+ /**
258
+ * Create a list of {@link SingleRecyclerViewMatrixLocation} objects to eventually use in the RecyclerView.
259
+ */
232
260
private void initMatrixLocationListForRecyclerView () {
233
261
matrixLocationList = new ArrayList <>();
234
- if (featureCollection .features () != null ) {
262
+ if (featureCollection != null && featureCollection .features () != null ) {
235
263
for (Feature feature : featureCollection .features ()) {
236
264
SingleRecyclerViewMatrixLocation singleRecyclerViewLocation = new SingleRecyclerViewMatrixLocation ();
237
- singleRecyclerViewLocation .setName (feature .getStringProperty ("Station_Name" ));
238
- singleRecyclerViewLocation .setLocationLatLng (new LatLng (((Point )
239
- feature .geometry ()).latitude (),
240
- ((Point ) feature .geometry ()).longitude ()));
265
+ singleRecyclerViewLocation .setName (feature .getStringProperty (STATION_NAME_PROPERTY ));
241
266
matrixLocationList .add (singleRecyclerViewLocation );
242
267
}
243
268
}
@@ -310,12 +335,11 @@ public String getDistanceFromOrigin() {
310
335
public void setDistanceFromOrigin (String distanceFromOrigin ) {
311
336
this .distanceFromOrigin = distanceFromOrigin ;
312
337
}
313
-
314
- public void setLocationLatLng (LatLng locationLatLng ) {
315
- this .locationLatLng = locationLatLng ;
316
- }
317
338
}
318
339
340
+ /**
341
+ * The adapter for this example's RecyclerView.
342
+ */
319
343
static class MatrixApiLocationRecyclerViewAdapter extends
320
344
RecyclerView .Adapter <MatrixApiLocationRecyclerViewAdapter .MyViewHolder > {
321
345
@@ -364,4 +388,4 @@ static class MyViewHolder extends RecyclerView.ViewHolder {
364
388
}
365
389
}
366
390
}
367
- }
391
+ }
0 commit comments