[android] make location provider optional (#9488) (#10354)

This commit is contained in:
Pablo Guardiola
2017-11-01 18:25:52 -07:00
committed by GitHub
parent d0d401b007
commit 29a94ae939
16 changed files with 279 additions and 116 deletions

View File

@@ -0,0 +1,107 @@
package com.mapbox.mapboxsdk;
import android.location.Location;
import android.support.annotation.Nullable;
import com.mapbox.mapboxsdk.location.LocationSource;
import com.mapbox.services.android.core.location.LocationEngine;
import com.mapbox.services.android.core.location.LocationEngineListener;
class EmptyLocationSource extends LocationSource {
/**
* Activate the location engine which will connect whichever location provider you are using. You'll need to call
* this before requesting user location updates using {@link LocationEngine#requestLocationUpdates()}.
*/
@Override
public void activate() {
// Intentionally left empty
}
/**
* Disconnect the location engine which is useful when you no longer need location updates or requesting the users
* {@link LocationEngine#getLastLocation()}. Before deactivating, you'll need to stop request user location updates
* using {@link LocationEngine#removeLocationUpdates()}.
*/
@Override
public void deactivate() {
// Intentionally left empty
}
/**
* Check if your location provider has been activated/connected. This is mainly used internally but is also useful in
* the rare case when you'd like to know if your location engine is connected or not.
*
* @return boolean true if the location engine has been activated/connected, else false.
*/
@Override
public boolean isConnected() {
return false;
}
/**
* Returns the Last known location is the location provider is connected and location permissions are granted.
*
* @return the last known location
*/
@Override
@Nullable
public Location getLastLocation() {
return null;
}
/**
* Request location updates to the location provider.
*/
@Override
public void requestLocationUpdates() {
// Intentionally left empty
}
/**
* Dismiss ongoing location update to the location provider.
*/
@Override
public void removeLocationUpdates() {
// Intentionally left empty
}
/**
* Invoked when the Location has changed.
*
* @param location the new location
*/
@Override
public void onLocationChanged(Location location) {
// Intentionally left empty
}
/**
* Useful when you'd like to add a location listener to handle location connections and update events. It is important
* to note, that the callback will continue getting called even when your application isn't in the foreground.
* Therefore, it is a good idea to use {@link LocationEngine#removeLocationEngineListener(LocationEngineListener)}
* inside your activities {@code onStop()} method.
*
* @param listener A {@link LocationEngineListener} which you'd like to add to your location engine.
* @since 2.0.0
*/
@Override
public void addLocationEngineListener(LocationEngineListener listener) {
// Intentionally left empty
}
/**
* If you no longer need your {@link LocationEngineListener} to be invoked with every location update, use this
* method to remove it. It's also important to remove your listeners before the activity is destroyed to prevent any
* potential memory leaks.
*
* @param listener the {@link LocationEngineListener} you'd like to remove from this {@link LocationEngine}.
* @return true.
* @since 2.0.0
*/
@Override
public boolean removeLocationEngineListener(LocationEngineListener listener) {
return true;
}
}

View File

@@ -12,9 +12,10 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
import com.mapbox.mapboxsdk.location.LocationSource;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
import com.mapbox.services.android.core.location.LocationEngine;
import com.mapbox.services.android.core.location.LocationEnginePriority;
import com.mapbox.services.android.core.location.LocationEngineProvider;
import com.mapbox.services.android.telemetry.MapboxTelemetry;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.telemetry.location.LocationEnginePriority;
import timber.log.Timber;
@@ -34,7 +35,7 @@ public final class Mapbox {
private Context context;
private String accessToken;
private Boolean connected;
private LocationSource locationSource;
private LocationEngine locationEngine;
/**
* Get an instance of Mapbox.
@@ -50,8 +51,9 @@ public final class Mapbox {
public static synchronized Mapbox getInstance(@NonNull Context context, @NonNull String accessToken) {
if (INSTANCE == null) {
Context appContext = context.getApplicationContext();
INSTANCE = new Mapbox(appContext, accessToken, new LocationSource(appContext));
LocationEngine locationEngine = new LocationSource(appContext);
LocationEngineProvider locationEngineProvider = new LocationEngineProvider(context);
LocationEngine locationEngine = locationEngineProvider.obtainBestLocationEngineAvailable();
INSTANCE = new Mapbox(appContext, accessToken, locationEngine);
locationEngine.setPriority(LocationEnginePriority.NO_POWER);
try {
@@ -66,10 +68,10 @@ public final class Mapbox {
return INSTANCE;
}
Mapbox(@NonNull Context context, @NonNull String accessToken, LocationSource locationSource) {
Mapbox(@NonNull Context context, @NonNull String accessToken, LocationEngine locationEngine) {
this.context = context;
this.accessToken = accessToken;
this.locationSource = locationSource;
this.locationEngine = locationEngine;
}
/**
@@ -143,7 +145,24 @@ public final class Mapbox {
return (activeNetwork != null && activeNetwork.isConnected());
}
/**
* Returns a location source instance with empty methods.
*
* @return an empty location source implementation
* @deprecated Replaced by {@link Mapbox#getLocationEngine()}
*/
@Deprecated
public static LocationSource getLocationSource() {
return INSTANCE.locationSource;
return new EmptyLocationSource();
}
/**
* Returns the location engine used by the SDK.
*
* @return the location engine configured
*/
public static LocationEngine getLocationEngine() {
return INSTANCE.locationEngine;
}
}

View File

@@ -4,16 +4,17 @@ import android.content.Context;
import android.location.Location;
import android.support.annotation.Nullable;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.telemetry.location.LocationEngineListener;
import com.mapbox.services.android.telemetry.location.LocationEnginePriority;
import com.mapbox.services.android.telemetry.permissions.PermissionsManager;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.services.android.core.location.LocationEngine;
import com.mapbox.services.android.core.location.LocationEngineListener;
import com.mapbox.services.android.core.location.LocationEnginePriority;
import com.mapzen.android.lost.api.LocationListener;
import com.mapzen.android.lost.api.LocationRequest;
import com.mapzen.android.lost.api.LocationServices;
import com.mapzen.android.lost.api.LostApiClient;
/**
* LocationEngine using the Open Source Lost library
* Manages locational updates. Contains methods to register and unregister location listeners.
* <ul>
* <li>You can register a LocationEngineListener with LocationSource#addLocationEngineListener(LocationEngineListener)
@@ -27,8 +28,11 @@ import com.mapzen.android.lost.api.LostApiClient;
* overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back
* in the history stack.
* </p>
*
* @deprecated Use a {@link Mapbox#getLocationEngine()} instead.
*/
public class LocationSource extends LocationEngine implements LocationListener {
@Deprecated
public class LocationSource extends LocationEngine implements LostApiClient.ConnectionCallbacks, LocationListener {
private Context context;
private LostApiClient lostApiClient;
@@ -41,7 +45,16 @@ public class LocationSource extends LocationEngine implements LocationListener {
public LocationSource(Context context) {
super();
this.context = context.getApplicationContext();
lostApiClient = new LostApiClient.Builder(this.context).build();
lostApiClient = new LostApiClient.Builder(this.context)
.addConnectionCallbacks(this)
.build();
}
/**
* Constructs a location source instance.
* Needed to create empty location source implementations.
*/
public LocationSource() {
}
/**
@@ -50,12 +63,9 @@ public class LocationSource extends LocationEngine implements LocationListener {
*/
@Override
public void activate() {
if (!lostApiClient.isConnected()) {
if (lostApiClient != null && !lostApiClient.isConnected()) {
lostApiClient.connect();
}
for (LocationEngineListener listener : locationListeners) {
listener.onConnected();
}
}
/**
@@ -65,7 +75,7 @@ public class LocationSource extends LocationEngine implements LocationListener {
*/
@Override
public void deactivate() {
if (lostApiClient.isConnected()) {
if (lostApiClient != null && lostApiClient.isConnected()) {
lostApiClient.disconnect();
}
}
@@ -81,6 +91,24 @@ public class LocationSource extends LocationEngine implements LocationListener {
return lostApiClient.isConnected();
}
/**
* Invoked when the location provider has connected.
*/
@Override
public void onConnected() {
for (LocationEngineListener listener : locationListeners) {
listener.onConnected();
}
}
/**
* Invoked when the location provider connection has been suspended.
*/
@Override
public void onConnectionSuspended() {
// Intentionally left empty
}
/**
* Returns the Last known location is the location provider is connected and location permissions are granted.
*
@@ -89,9 +117,9 @@ public class LocationSource extends LocationEngine implements LocationListener {
@Override
@Nullable
public Location getLastLocation() {
if (lostApiClient.isConnected() && PermissionsManager.areLocationPermissionsGranted(context)) {
if (lostApiClient.isConnected()) {
//noinspection MissingPermission
return LocationServices.FusedLocationApi.getLastLocation();
return LocationServices.FusedLocationApi.getLastLocation(lostApiClient);
}
return null;
}
@@ -101,13 +129,18 @@ public class LocationSource extends LocationEngine implements LocationListener {
*/
@Override
public void requestLocationUpdates() {
// Common params
LocationRequest request = LocationRequest.create()
.setInterval(1000)
.setFastestInterval(1000)
.setSmallestDisplacement(3.0f);
LocationRequest request = LocationRequest.create();
if (interval != null) {
request.setInterval(interval);
}
if (fastestInterval != null) {
request.setFastestInterval(fastestInterval);
}
if (smallestDisplacement != null) {
request.setSmallestDisplacement(smallestDisplacement);
}
// Priority matching is straightforward
if (priority == LocationEnginePriority.NO_POWER) {
request.setPriority(LocationRequest.PRIORITY_NO_POWER);
} else if (priority == LocationEnginePriority.LOW_POWER) {
@@ -118,9 +151,9 @@ public class LocationSource extends LocationEngine implements LocationListener {
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
if (lostApiClient.isConnected() && PermissionsManager.areLocationPermissionsGranted(context)) {
if (lostApiClient.isConnected()) {
//noinspection MissingPermission
LocationServices.FusedLocationApi.requestLocationUpdates(request, this);
LocationServices.FusedLocationApi.requestLocationUpdates(lostApiClient, request, this);
}
}
@@ -130,10 +163,20 @@ public class LocationSource extends LocationEngine implements LocationListener {
@Override
public void removeLocationUpdates() {
if (lostApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(this);
LocationServices.FusedLocationApi.removeLocationUpdates(lostApiClient, this);
}
}
/**
* Returns the location engine type.
*
* @return Lost type
*/
@Override
public Type obtainType() {
return Type.LOST;
}
/**
* Invoked when the Location has changed.
*
@@ -145,4 +188,4 @@ public class LocationSource extends LocationEngine implements LocationListener {
listener.onLocationChanged(location);
}
}
}
}

View File

@@ -1,4 +1,4 @@
/**
* Contains the Mapbox Maps Android Location API classes.
*/
package com.mapbox.mapboxsdk.location;
package com.mapbox.mapboxsdk.location;

View File

@@ -42,7 +42,7 @@ import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.light.Light;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.core.location.LocationEngine;
import com.mapbox.services.commons.geojson.Feature;
import com.mapbox.services.commons.geojson.Geometry;

View File

@@ -12,8 +12,8 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.telemetry.location.LocationEngineListener;
import com.mapbox.services.android.core.location.LocationEngine;
import com.mapbox.services.android.core.location.LocationEngineListener;
import com.mapbox.services.android.telemetry.permissions.PermissionsManager;
import timber.log.Timber;
@@ -52,7 +52,7 @@ public final class TrackingSettings {
}
void initialise(MapboxMapOptions options) {
locationSource = Mapbox.getLocationSource();
locationSource = Mapbox.getLocationEngine();
setMyLocationEnabled(options.getLocationEnabled());
}
@@ -392,7 +392,7 @@ public final class TrackingSettings {
this.isCustomLocationSource = locationSource != null;
if (locationSource == null) {
locationSource = Mapbox.getLocationSource();
locationSource = Mapbox.getLocationEngine();
}
this.locationSource = locationSource;
myLocationView.setLocationSource(locationSource);

View File

@@ -36,9 +36,9 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.LocationSource;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Projection;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.telemetry.location.LocationEngineListener;
import com.mapbox.services.android.telemetry.location.LocationEnginePriority;
import com.mapbox.services.android.core.location.LocationEngine;
import com.mapbox.services.android.core.location.LocationEngineListener;
import com.mapbox.services.android.core.location.LocationEnginePriority;
import java.lang.ref.WeakReference;
@@ -70,7 +70,7 @@ public class MyLocationView extends View {
private LatLng latLng;
private Location location;
private LocationEngine locationSource;
private LocationEngine locationEngine;
private long locationUpdateTimestamp;
private float previousDirection;
@@ -161,8 +161,9 @@ public class MyLocationView extends View {
compassListener = new CompassListener(context);
}
@Deprecated
public void init(LocationSource locationSource) {
this.locationSource = locationSource;
this.locationEngine = locationSource;
}
/**
@@ -448,8 +449,8 @@ public class MyLocationView extends View {
}
if (userLocationListener != null) {
locationSource.removeLocationEngineListener(userLocationListener);
locationSource = null;
locationEngine.removeLocationEngineListener(userLocationListener);
locationEngine = null;
userLocationListener = null;
}
}
@@ -485,12 +486,12 @@ public class MyLocationView extends View {
* Set the enabled state, for internal use only.
*
* @param enabled The value to set the state to
* @param isCustomLocationSource Flag handling for handling user provided custom location source
* @param isCustomLocationEngine Flag handling for handling user provided custom location engine
*/
public void setEnabled(boolean enabled, boolean isCustomLocationSource) {
public void setEnabled(boolean enabled, boolean isCustomLocationEngine) {
super.setEnabled(enabled);
setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
toggleGps(enabled, isCustomLocationSource);
toggleGps(enabled, isCustomLocationEngine);
}
/**
@@ -530,32 +531,33 @@ public class MyLocationView extends View {
*
* @param enableGps true if GPS is to be enabled, false if GPS is to be disabled
*/
private void toggleGps(boolean enableGps, boolean isCustomLocationSource) {
private void toggleGps(boolean enableGps, boolean isCustomLocationEngine) {
if (enableGps) {
if (locationSource == null) {
if (!isCustomLocationSource) {
locationSource = Mapbox.getLocationSource();
if (locationEngine == null) {
if (!isCustomLocationEngine) {
locationEngine = Mapbox.getLocationEngine();
} else {
return;
}
}
if (userLocationListener == null) {
userLocationListener = new GpsLocationListener(this, locationSource);
userLocationListener = new GpsLocationListener(this, locationEngine);
}
locationSource.addLocationEngineListener(userLocationListener);
locationSource.setPriority(LocationEnginePriority.HIGH_ACCURACY);
locationSource.activate();
locationEngine.addLocationEngineListener(userLocationListener);
locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
locationEngine.activate();
} else {
if (locationSource == null) {
if (locationEngine == null) {
return;
}
// Disable location and user dot
location = null;
locationSource.removeLocationEngineListener(userLocationListener);
locationSource.removeLocationUpdates();
locationSource.deactivate();
locationEngine.removeLocationEngineListener(userLocationListener);
locationEngine.removeLocationUpdates();
locationEngine.deactivate();
restoreLocationEngine();
}
}
@@ -740,13 +742,13 @@ public class MyLocationView extends View {
/**
* Set the location source from which location updates are received, for internal use only.
*
* @param locationSource The location source to receive updates from
* @param locationEngine The location engine to receive updates from
*/
public void setLocationSource(LocationEngine locationSource) {
public void setLocationSource(LocationEngine locationEngine) {
toggleGps(false);
this.locationSource = locationSource;
this.locationEngine = locationEngine;
this.userLocationListener = null;
setEnabled(isEnabled(), locationSource != null);
setEnabled(isEnabled(), locationEngine != null);
}
private void applyDrawableTint(Drawable drawable, @ColorInt int color) {
@@ -769,6 +771,11 @@ public class MyLocationView extends View {
}
}
private void restoreLocationEngine() {
locationEngine.setPriority(LocationEnginePriority.LOW_POWER);
locationEngine.activate();
}
private static class GpsLocationListener implements LocationEngineListener {
private WeakReference<MyLocationView> userLocationView;