33import android .arch .lifecycle .Observer ;
44import android .arch .lifecycle .ViewModelProviders ;
55import android .content .Intent ;
6+ import android .location .Location ;
67import android .os .Bundle ;
78import android .support .annotation .NonNull ;
89import android .support .annotation .Nullable ;
1516import android .view .Window ;
1617import android .view .animation .OvershootInterpolator ;
1718import android .widget .ImageView ;
19+ import android .widget .Toast ;
1820
1921import com .google .gson .JsonObject ;
22+ import com .mapbox .android .core .permissions .PermissionsListener ;
23+ import com .mapbox .android .core .permissions .PermissionsManager ;
2024import com .mapbox .api .geocoding .v5 .models .CarmenFeature ;
2125import com .mapbox .geojson .Point ;
26+ import com .mapbox .mapboxsdk .camera .CameraPosition ;
2227import com .mapbox .mapboxsdk .camera .CameraUpdateFactory ;
2328import com .mapbox .mapboxsdk .geometry .LatLng ;
29+ import com .mapbox .mapboxsdk .location .LocationComponent ;
30+ import com .mapbox .mapboxsdk .location .LocationComponentActivationOptions ;
31+ import com .mapbox .mapboxsdk .location .modes .CameraMode ;
32+ import com .mapbox .mapboxsdk .location .modes .RenderMode ;
2433import com .mapbox .mapboxsdk .maps .MapView ;
2534import com .mapbox .mapboxsdk .maps .MapboxMap ;
2635import com .mapbox .mapboxsdk .maps .OnMapReadyCallback ;
3342import com .mapbox .mapboxsdk .plugins .places .picker .model .PlacePickerOptions ;
3443import com .mapbox .mapboxsdk .plugins .places .picker .viewmodel .PlacePickerViewModel ;
3544
45+ import java .util .List ;
3646import java .util .Locale ;
3747
3848import timber .log .Timber ;
4656 * @since 0.2.0
4757 */
4858public class PlacePickerActivity extends AppCompatActivity implements OnMapReadyCallback ,
49- MapboxMap .OnCameraMoveStartedListener , MapboxMap .OnCameraIdleListener , Observer <CarmenFeature > {
59+ MapboxMap .OnCameraMoveStartedListener , MapboxMap .OnCameraIdleListener , Observer <CarmenFeature >,
60+ PermissionsListener {
5061
62+ private PermissionsManager permissionsManager ;
5163 CurrentPlaceSelectionBottomSheet bottomSheet ;
5264 CarmenFeature carmenFeature ;
5365 private PlacePickerViewModel viewModel ;
@@ -56,6 +68,7 @@ public class PlacePickerActivity extends AppCompatActivity implements OnMapReady
5668 private MapboxMap mapboxMap ;
5769 private String accessToken ;
5870 private MapView mapView ;
71+ private FloatingActionButton userLocationButton ;
5972 private boolean includeReverseGeocode ;
6073
6174 @ Override
@@ -105,6 +118,12 @@ private void bindViews() {
105118 mapView = findViewById (R .id .map_view );
106119 bottomSheet = findViewById (R .id .mapbox_plugins_picker_bottom_sheet );
107120 markerImage = findViewById (R .id .mapbox_plugins_image_view_marker );
121+ userLocationButton = findViewById (R .id .user_location_button );
122+ }
123+
124+ private void bindListeners () {
125+ PlacePickerActivity .this .mapboxMap .addOnCameraMoveStartedListener (PlacePickerActivity .this );
126+ PlacePickerActivity .this .mapboxMap .addOnCameraIdleListener (PlacePickerActivity .this );
108127 }
109128
110129 private void customizeViews () {
@@ -123,25 +142,85 @@ public void onMapReady(final MapboxMap mapboxMap) {
123142 mapboxMap .setStyle (Style .MAPBOX_STREETS , new Style .OnStyleLoaded () {
124143 @ Override
125144 public void onStyleLoaded (@ NonNull Style style ) {
126- if (options != null ) {
127- if (options .startingBounds () != null ) {
128- mapboxMap .moveCamera (CameraUpdateFactory .newLatLngBounds (options .startingBounds (), 0 ));
129- } else if (options .statingCameraPosition () != null ) {
130- mapboxMap .moveCamera (CameraUpdateFactory .newCameraPosition (options .statingCameraPosition ()));
131- }
132- }
133-
145+ adjustCameraBasedOnOptions ();
134146 if (includeReverseGeocode ) {
135- // Initialize with the markers current location information .
147+ // Initialize with the marker's current coordinates .
136148 makeReverseGeocodingSearch ();
137149 }
150+ bindListeners ();
138151
139- PlacePickerActivity .this .mapboxMap .addOnCameraMoveStartedListener (PlacePickerActivity .this );
140- PlacePickerActivity .this .mapboxMap .addOnCameraIdleListener (PlacePickerActivity .this );
152+ if (options != null && options .includeDeviceLocationButton ()) {
153+ enableLocationComponent (style );
154+ } else {
155+ userLocationButton .hide ();
156+ }
141157 }
142158 });
143159 }
144160
161+ private void adjustCameraBasedOnOptions () {
162+ if (options != null ) {
163+ if (options .startingBounds () != null ) {
164+ mapboxMap .moveCamera (CameraUpdateFactory .newLatLngBounds (options .startingBounds (), 0 ));
165+ } else if (options .statingCameraPosition () != null ) {
166+ mapboxMap .moveCamera (CameraUpdateFactory .newCameraPosition (options .statingCameraPosition ()));
167+ }
168+ }
169+ }
170+
171+ @ SuppressWarnings ( {"MissingPermission" })
172+ private void enableLocationComponent (@ NonNull Style loadedMapStyle ) {
173+ // Check if permissions are enabled and if not request
174+ if (PermissionsManager .areLocationPermissionsGranted (this )) {
175+
176+ // Get an instance of the component
177+ LocationComponent locationComponent = mapboxMap .getLocationComponent ();
178+
179+ // Activate with options
180+ locationComponent .activateLocationComponent (
181+ LocationComponentActivationOptions .builder (this , loadedMapStyle ).build ());
182+
183+ // Enable to make component visible
184+ locationComponent .setLocationComponentEnabled (true );
185+
186+ // Set the component's camera mode
187+ locationComponent .setCameraMode (CameraMode .NONE );
188+
189+ // Set the component's render mode
190+ locationComponent .setRenderMode (RenderMode .NORMAL );
191+
192+ addUserLocationButton ();
193+ } else {
194+ permissionsManager = new PermissionsManager (this );
195+ permissionsManager .requestLocationPermissions (this );
196+ }
197+ }
198+
199+ @ Override
200+ public void onRequestPermissionsResult (int requestCode , @ NonNull String [] permissions , @ NonNull int [] grantResults ) {
201+ permissionsManager .onRequestPermissionsResult (requestCode , permissions , grantResults );
202+ }
203+
204+ @ Override
205+ public void onExplanationNeeded (List <String > permissionsToExplain ) {
206+ Toast .makeText (this , R .string .mapbox_plugins_place_picker_user_location_permission_explanation ,
207+ Toast .LENGTH_LONG ).show ();
208+ }
209+
210+ @ Override
211+ public void onPermissionResult (boolean granted ) {
212+ if (granted ) {
213+ mapboxMap .getStyle (new Style .OnStyleLoaded () {
214+ @ Override
215+ public void onStyleLoaded (@ NonNull Style style ) {
216+ if (options != null && options .includeDeviceLocationButton ()) {
217+ enableLocationComponent (style );
218+ }
219+ }
220+ });
221+ }
222+ }
223+
145224 @ Override
146225 public void onCameraMoveStarted (int reason ) {
147226 Timber .v ("Map camera has begun moving." );
@@ -185,8 +264,8 @@ private void makeReverseGeocodingSearch() {
185264 LatLng latLng = mapboxMap .getCameraPosition ().target ;
186265 if (latLng != null ) {
187266 viewModel .reverseGeocode (
188- Point .fromLngLat (latLng .getLongitude (), latLng .getLatitude ()),
189- accessToken , options
267+ Point .fromLngLat (latLng .getLongitude (), latLng .getLatitude ()),
268+ accessToken , options
190269 );
191270 }
192271 }
@@ -207,6 +286,32 @@ public void onClick(View view) {
207286 });
208287 }
209288
289+ /**
290+ * Bind the device location Floating Action Button to this activity's UI and move the
291+ * map camera if the button's clicked.
292+ */
293+ private void addUserLocationButton () {
294+ userLocationButton .show ();
295+ userLocationButton .setOnClickListener (new View .OnClickListener () {
296+ @ Override
297+ public void onClick (View view ) {
298+ if (mapboxMap .getLocationComponent ().getLastKnownLocation () != null ) {
299+ Location lastKnownLocation = mapboxMap .getLocationComponent ().getLastKnownLocation ();
300+ mapboxMap .animateCamera (CameraUpdateFactory .newCameraPosition (
301+ new CameraPosition .Builder ()
302+ .target (new LatLng (lastKnownLocation .getLatitude (),
303+ lastKnownLocation .getLongitude ()))
304+ .zoom (17.5 )
305+ .build ()
306+ ),1400 );
307+ } else {
308+ Toast .makeText (PlacePickerActivity .this ,
309+ getString (R .string .mapbox_plugins_place_picker_user_location_not_found ), Toast .LENGTH_SHORT ).show ();
310+ }
311+ }
312+ });
313+ }
314+
210315 void placeSelected () {
211316 Intent returningIntent = new Intent ();
212317 if (includeReverseGeocode ) {
0 commit comments