[android] Remove com.google.android.gms.location (#379) (#801)

This commit is contained in:
Bart Louwers
2023-02-15 11:22:44 +01:00
committed by GitHub
parent 4a34caab75
commit 982ac6e7e3
19 changed files with 83 additions and 771 deletions

View File

@@ -6,12 +6,16 @@ MapLibre welcomes participation and contributions from everyone. Please read [`C
* Add your pull request...
## 10.0.0 - February 10, 2023
## 10.0.0 - February 14, 2023
### ✨ Features and improvements
* Breaking: Changed resourcePrefix to `maplibre_` from `mapbox_` [647](https://github.com/maplibre/maplibre-gl-native/pull/647) and renamed resources accordingly. Note that this is a breaking change since the names of public resources were renamed as well. Replaced Mapbox logo with MapLibre logo.
* GMS location: Replace new LocationRequest() with LocationRequest.Builder, and LocationRequest.PRIORITY_X with Priority.PRIORITY_X ([620](https://github.com/maplibre/maplibre-gl-native/pull/620))
* Breaking: Changed resourcePrefix to `maplibre_` from `mapbox_` ([#647](https://github.com/maplibre/maplibre-gl-native/pull/647)) and renamed resources accordingly. Note that this is a breaking change since the names of public resources were renamed as well. Replaced Mapbox logo with MapLibre logo.
* Breaking: several deprecated overloads of `LocationComponent.activateLocationComponent` were removed. Use `LocationComponentActivationOptions.Builder` instead.
* Breaking: the `LocationEngine` implemented with Google Location Services has been removed to make MapLibre GL Native for Android fully FLOSS ([#379](https://github.com/maplibre/maplibre-gl-native/issues/379)). To migrate:
* Include the source code of the removed [`GoogleLocationEngineImpl`](https://github.com/maplibre/maplibre-gl-native/blob/4a34caab7593f4f1b6d8c09c06a5e25d7c6cfc43/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/engine/GoogleLocationEngineImpl.java) in your source tree.
* Pass an instance of `LocationEngine` based on `GoogleLocationEngineImpl` to `LocationComponentActivationOptions.Builder.locationEngine`. Refer to how this was done in the now-removed [`LocationEngineProvider`](https://github.com/maplibre/maplibre-gl-native/blob/68d58d6f6f453d5c6cc0fa92fcc6c6cfe0cf967f/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/engine/LocationEngineProvider.java#L59).
* The static `LocationEngineResult.extractResult` can no longer extract a `LocationEngineResult` from a Google Play intent. To migrate, include and use the [previous implementation](https://github.com/maplibre/maplibre-gl-native/blob/ea234edf67bb3aec75f077e15c1c30c99756b926/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/engine/LocationEngineResult.java#L97) in your source tree.
### 🐞 Bug fixes

View File

@@ -17,7 +17,6 @@ dependencies {
implementation dependenciesList.supportAnnotations
implementation dependenciesList.supportFragmentV4
implementation dependenciesList.okhttp3
implementation dependenciesList.gmsLocation
implementation dependenciesList.timber
implementation dependenciesList.interpolator

View File

@@ -40,7 +40,8 @@ class LatLng : Parcelable {
@Keep
var latitude = 0.0
set(
@FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) latitude) {
@FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) latitude
) {
require(!latitude.isNaN()) { "latitude must not be NaN" }
require(abs(latitude) <= GeometryConstants.MAX_LATITUDE) { "latitude must be between -90 and 90" }
field = latitude

View File

@@ -20,7 +20,7 @@ import com.mapbox.mapboxsdk.camera.CameraUpdate;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.engine.LocationEngine;
import com.mapbox.mapboxsdk.location.engine.LocationEngineCallback;
import com.mapbox.mapboxsdk.location.engine.LocationEngineProvider;
import com.mapbox.mapboxsdk.location.engine.LocationEngineDefault;
import com.mapbox.mapboxsdk.location.engine.LocationEngineRequest;
import com.mapbox.mapboxsdk.location.engine.LocationEngineResult;
import com.mapbox.mapboxsdk.location.modes.CameraMode;
@@ -66,7 +66,7 @@ import static com.mapbox.mapboxsdk.location.modes.RenderMode.GPS;
* <p>
* <strong>
* To get the component object use {@link MapboxMap#getLocationComponent()} and activate it with
* {@link #activateLocationComponent(Context, Style)} or one of the overloads.
* {@link #activateLocationComponent(LocationComponentActivationOptions)}.
* Then, manage its visibility with {@link #setLocationComponentEnabled(boolean)}.
* The component will not process location updates right after activation, but only after being enabled.
* </strong>
@@ -76,19 +76,17 @@ import static com.mapbox.mapboxsdk.location.modes.RenderMode.GPS;
* {@code ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION} permissions can be requested for
* this component to work as expected.
* <p>
* This component offers a default, built-in {@link LocationEngine} with some of the activation methods.
* This engine will be obtained by {@link LocationEngineProvider#getBestLocationEngine(Context, boolean)} which defaults
* to the {@link com.mapbox.mapboxsdk.location.engine.MapboxFusedLocationEngineImpl}. If you'd like to utilize Google
* Play Services
* for more precise location updates, simply add the Google Play Location Services dependency in your build script.
* This will make the default engine the {@link com.mapbox.mapboxsdk.location.engine.GoogleLocationEngineImpl} instead.
* This component offers a default, built-in {@link LocationEngine} called
* {@link com.mapbox.mapboxsdk.location.engine.MapboxFusedLocationEngineImpl}.
* If you'd like to utilize the previously available Google Play Services for more precise location updates,
* refer to the migration guide of 10.0.0 in the changelog.
* After a custom engine is passed to the component, or the built-in is initialized,
* the location updates are going to be requested with the {@link LocationEngineRequest}, either a default one,
* or the one passed during the activation.
* When using any engine, requesting/removing the location updates is going to be managed internally.
* <p>
* You can also push location updates to the component without any internal engine management.
* To achieve that, use {@link #activateLocationComponent(Context, Style, boolean)} with false.
* To achieve that, set `useDefaultLocationEngine` in {@link LocationComponentActivationOptions} to false.
* No engine is going to be initialized and you can push location updates with {@link #forceLocationUpdate(Location)}.
* <p>
* For location puck animation purposes, like navigation,
@@ -105,8 +103,6 @@ public final class LocationComponent {
private final Transform transform;
private Style style;
private LocationComponentOptions options;
@NonNull
private InternalLocationEngineProvider internalLocationEngineProvider = new InternalLocationEngineProvider();
@Nullable
private LocationEngine locationEngine;
@NonNull
@@ -218,7 +214,6 @@ public final class LocationComponent {
@NonNull LocationAnimatorCoordinator locationAnimatorCoordinator,
@NonNull StaleStateManager staleStateManager,
@NonNull CompassEngine compassEngine,
@NonNull InternalLocationEngineProvider internalLocationEngineProvider,
boolean useSpecializedLocationLayer) {
this.mapboxMap = mapboxMap;
this.transform = transform;
@@ -230,242 +225,10 @@ public final class LocationComponent {
this.locationAnimatorCoordinator = locationAnimatorCoordinator;
this.staleStateManager = staleStateManager;
this.compassEngine = compassEngine;
this.internalLocationEngineProvider = internalLocationEngineProvider;
this.useSpecializedLocationLayer = useSpecializedLocationLayer;
isComponentInitialized = true;
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
* <p>
* <strong>Note</strong>: This method will initialize and use an internal {@link LocationEngine} when enabled.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style) {
activateLocationComponent(context, style,
LocationComponentOptions.createFromAttributes(context, R.style.maplibre_LocationComponent));
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param useDefaultLocationEngine true if you want to initialize and use the built-in location engine or false if
* there should be no location engine initialized
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
boolean useDefaultLocationEngine) {
if (useDefaultLocationEngine) {
activateLocationComponent(context, style, R.style.maplibre_LocationComponent);
} else {
activateLocationComponent(context, style, null, R.style.maplibre_LocationComponent);
}
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param useDefaultLocationEngine true if you want to initialize and use the built-in location engine or false if
* there should be no location engine initialized
* @param locationEngineRequest the location request
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
boolean useDefaultLocationEngine,
@NonNull LocationEngineRequest locationEngineRequest) {
setLocationEngineRequest(locationEngineRequest);
if (useDefaultLocationEngine) {
activateLocationComponent(context, style, R.style.maplibre_LocationComponent);
} else {
activateLocationComponent(context, style, null, R.style.maplibre_LocationComponent);
}
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param useDefaultLocationEngine true if you want to initialize and use the built-in location engine or false if
* there should be no location engine initialized
* @param locationEngineRequest the location request
* @param options the options
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
boolean useDefaultLocationEngine,
@NonNull LocationEngineRequest locationEngineRequest,
@NonNull LocationComponentOptions options) {
setLocationEngineRequest(locationEngineRequest);
if (useDefaultLocationEngine) {
activateLocationComponent(context, style, options);
} else {
activateLocationComponent(context, style, null, options);
}
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
* <p>
* <strong>Note</strong>: This method will initialize and use an internal {@link LocationEngine} when enabled.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param styleRes the LocationComponent style res
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style, @StyleRes int styleRes) {
activateLocationComponent(context, style, LocationComponentOptions.createFromAttributes(context, styleRes));
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
* <p>
* <strong>Note</strong>: This method will initialize and use an internal {@link LocationEngine} when enabled.
* </p>
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param options the options
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@NonNull LocationComponentOptions options) {
initialize(context, style, false, options);
initializeLocationEngine(context);
applyStyle(options);
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param locationEngine the engine, or null if you'd like to only force location updates
* @param styleRes the LocationComponent style res
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine, @StyleRes int styleRes) {
activateLocationComponent(context, style, locationEngine,
LocationComponentOptions.createFromAttributes(context, styleRes));
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param locationEngine the engine, or null if you'd like to only force location updates
* @param locationEngineRequest the location request
* @param styleRes the LocationComponent style res
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine,
@NonNull LocationEngineRequest locationEngineRequest, @StyleRes int styleRes) {
activateLocationComponent(context, style, locationEngine, locationEngineRequest,
LocationComponentOptions.createFromAttributes(context, styleRes));
}
/**
* This method will show the location icon and enable the camera tracking the location.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param locationEngine the engine
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine) {
activateLocationComponent(context, style, locationEngine, R.style.maplibre_LocationComponent);
}
/**
* This method will show the location icon and enable the camera tracking the location.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param locationEngine the engine
* @param locationEngineRequest the location request
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine,
@NonNull LocationEngineRequest locationEngineRequest) {
activateLocationComponent(
context,
style,
locationEngine,
locationEngineRequest,
R.style.maplibre_LocationComponent);
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
*
* @param locationEngine the engine, or null if you'd like to only force location updates
* @param style the proxy object for current map style. More info at {@link Style}
* @param options the options
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine,
@NonNull LocationComponentOptions options) {
initialize(context, style, false, options);
setLocationEngine(locationEngine);
applyStyle(options);
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
*
* @param context the context
* @param style the proxy object for current map style. More info at {@link Style}
* @param locationEngine the engine, or null if you'd like to only force location updates
* @param locationEngineRequest the location request
* @param options the options
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine,
@NonNull LocationEngineRequest locationEngineRequest,
@NonNull LocationComponentOptions options) {
initialize(context, style, false, options);
setLocationEngineRequest(locationEngineRequest);
setLocationEngine(locationEngine);
applyStyle(options);
}
/**
* This method initializes the component and needs to be called before any other operations are performed.
* Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}.
@@ -503,7 +266,7 @@ public final class LocationComponent {
setLocationEngine(locationEngine);
} else {
if (activationOptions.useDefaultLocationEngine()) {
initializeLocationEngine(activationOptions.context());
setLocationEngine(LocationEngineDefault.INSTANCE.getDefaultLocationEngine(activationOptions.context()));
} else {
setLocationEngine(null);
}
@@ -1354,13 +1117,6 @@ public final class LocationComponent {
onLocationLayerStart();
}
private void initializeLocationEngine(@NonNull Context context) {
if (this.locationEngine != null) {
this.locationEngine.removeLocationUpdates(currentLocationEngineListener);
}
setLocationEngine(internalLocationEngineProvider.getBestLocationEngine(context, false));
}
private void updateCompassListenerState(boolean canListen) {
if (compassEngine != null) {
if (!canListen) {
@@ -1712,12 +1468,6 @@ public final class LocationComponent {
}
};
static class InternalLocationEngineProvider {
LocationEngine getBestLocationEngine(@NonNull Context context, boolean background) {
return LocationEngineProvider.getBestLocationEngine(context, background);
}
}
private void checkActivationState() {
if (!isComponentInitialized) {
throw new LocationComponentNotInitializedException();

View File

@@ -1,146 +0,0 @@
package com.mapbox.mapboxsdk.location.engine;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.location.Location;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.Priority;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import java.util.Collections;
import java.util.List;
/**
* Wraps implementation of Fused Location Provider
*/
class GoogleLocationEngineImpl implements LocationEngineImpl<LocationCallback> {
private final FusedLocationProviderClient fusedLocationProviderClient;
@VisibleForTesting
GoogleLocationEngineImpl(FusedLocationProviderClient fusedLocationProviderClient) {
this.fusedLocationProviderClient = fusedLocationProviderClient;
}
GoogleLocationEngineImpl(@NonNull Context context) {
this.fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
}
@NonNull
@Override
public LocationCallback createListener(LocationEngineCallback<LocationEngineResult> callback) {
return new GoogleLocationEngineCallbackTransport(callback);
}
@SuppressLint("MissingPermission")
@Override
public void getLastLocation(@NonNull LocationEngineCallback<LocationEngineResult> callback)
throws SecurityException {
GoogleLastLocationEngineCallbackTransport transport =
new GoogleLastLocationEngineCallbackTransport(callback);
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(transport).addOnFailureListener(transport);
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull LocationCallback listener,
@Nullable Looper looper) throws SecurityException {
fusedLocationProviderClient.requestLocationUpdates(toGMSLocationRequest(request), listener, looper);
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(@NonNull LocationEngineRequest request,
@NonNull PendingIntent pendingIntent) throws SecurityException {
fusedLocationProviderClient.requestLocationUpdates(toGMSLocationRequest(request), pendingIntent);
}
@Override
public void removeLocationUpdates(@NonNull LocationCallback listener) {
if (listener != null) {
fusedLocationProviderClient.removeLocationUpdates(listener);
}
}
@Override
public void removeLocationUpdates(PendingIntent pendingIntent) {
if (pendingIntent != null) {
fusedLocationProviderClient.removeLocationUpdates(pendingIntent);
}
}
private static LocationRequest toGMSLocationRequest(LocationEngineRequest request) {
LocationRequest.Builder builder = new LocationRequest.Builder(request.getInterval());
builder.setMinUpdateIntervalMillis(request.getFastestInterval());
builder.setMinUpdateDistanceMeters(request.getDisplacement());
builder.setMaxUpdateDelayMillis(request.getMaxWaitTime());
builder.setPriority(toGMSLocationPriority(request.getPriority()));
return builder.build();
}
private static int toGMSLocationPriority(int enginePriority) {
switch (enginePriority) {
case LocationEngineRequest.PRIORITY_HIGH_ACCURACY:
return Priority.PRIORITY_HIGH_ACCURACY;
case LocationEngineRequest.PRIORITY_BALANCED_POWER_ACCURACY:
return Priority.PRIORITY_BALANCED_POWER_ACCURACY;
case LocationEngineRequest.PRIORITY_LOW_POWER:
return Priority.PRIORITY_LOW_POWER;
case LocationEngineRequest.PRIORITY_NO_POWER:
default:
return Priority.PRIORITY_PASSIVE;
}
}
private static final class GoogleLocationEngineCallbackTransport extends LocationCallback {
private final LocationEngineCallback<LocationEngineResult> callback;
GoogleLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
this.callback = callback;
}
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
List<Location> locations = locationResult.getLocations();
if (!locations.isEmpty()) {
callback.onSuccess(LocationEngineResult.create(locations));
} else {
callback.onFailure(new Exception("Unavailable location"));
}
}
}
@VisibleForTesting
static final class GoogleLastLocationEngineCallbackTransport
implements OnSuccessListener<Location>, OnFailureListener {
private final LocationEngineCallback<LocationEngineResult> callback;
GoogleLastLocationEngineCallbackTransport(LocationEngineCallback<LocationEngineResult> callback) {
this.callback = callback;
}
@Override
public void onSuccess(Location location) {
callback.onSuccess(location != null ? LocationEngineResult.create(location) :
LocationEngineResult.create(Collections.<Location>emptyList()));
}
@Override
public void onFailure(@NonNull Exception e) {
callback.onFailure(e);
}
}
}

View File

@@ -0,0 +1,12 @@
package com.mapbox.mapboxsdk.location.engine
import android.content.Context
object LocationEngineDefault {
/**
* Returns the default `LocationEngine`.
*/
fun getDefaultLocationEngine(context: Context): LocationEngine {
return LocationEngineProxy(MapboxFusedLocationEngineImpl(context.applicationContext))
}
}

View File

@@ -11,7 +11,7 @@ import androidx.annotation.Nullable;
*
* @param <T> location listener object type
*/
interface LocationEngineImpl<T> {
public interface LocationEngineImpl<T> {
@NonNull
T createListener(LocationEngineCallback<LocationEngineResult> callback);

View File

@@ -1,62 +0,0 @@
package com.mapbox.mapboxsdk.location.engine;
import android.content.Context;
import androidx.annotation.NonNull;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import static com.mapbox.mapboxsdk.location.engine.Utils.checkNotNull;
import static com.mapbox.mapboxsdk.location.engine.Utils.isOnClasspath;
/**
* The main entry point for location engine integration.
*/
public final class LocationEngineProvider {
private static final String GOOGLE_LOCATION_SERVICES = "com.google.android.gms.location.LocationServices";
private static final String GOOGLE_API_AVAILABILITY = "com.google.android.gms.common.GoogleApiAvailability";
private LocationEngineProvider() {
// prevent instantiation
}
/**
* Returns instance to the best location engine, given the included libraries.
*
* @param context {@link Context}.
* @param background true if background optimized engine is desired (note: parameter deprecated)
* @return a unique instance of {@link LocationEngine} every time method is called.
* @since 1.0.0
*/
@NonNull
@Deprecated
public static LocationEngine getBestLocationEngine(@NonNull Context context, boolean background) {
return getBestLocationEngine(context);
}
/**
* Returns instance to the best location engine, given the included libraries.
*
* @param context {@link Context}.
* @return a unique instance of {@link LocationEngine} every time method is called.
* @since 1.1.0
*/
@NonNull
public static LocationEngine getBestLocationEngine(@NonNull Context context) {
checkNotNull(context, "context == null");
boolean hasGoogleLocationServices = isOnClasspath(GOOGLE_LOCATION_SERVICES);
if (isOnClasspath(GOOGLE_API_AVAILABILITY)) {
// Check Google Play services APK is available and up-to-date on this device
hasGoogleLocationServices &= GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
== ConnectionResult.SUCCESS;
}
return getLocationEngine(context, hasGoogleLocationServices);
}
private static LocationEngine getLocationEngine(Context context, boolean isGoogle) {
return isGoogle ? new LocationEngineProxy<>(new GoogleLocationEngineImpl(context.getApplicationContext())) :
new LocationEngineProxy<>(new MapboxFusedLocationEngineImpl(context.getApplicationContext()));
}
}

View File

@@ -12,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
import static com.mapbox.mapboxsdk.location.engine.Utils.checkNotNull;
class LocationEngineProxy<T> implements LocationEngine {
public class LocationEngineProxy<T> implements LocationEngine {
private final LocationEngineImpl<T> locationEngineImpl;
private Map<LocationEngineCallback<LocationEngineResult>, T> listeners;

View File

@@ -7,14 +7,10 @@ import android.location.LocationManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.location.LocationResult;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.mapbox.mapboxsdk.location.engine.Utils.isOnClasspath;
/**
* A wrapper class representing location result from the location engine.
* <p>
@@ -23,8 +19,6 @@ import static com.mapbox.mapboxsdk.location.engine.Utils.isOnClasspath;
* @since 1.0.0
*/
public final class LocationEngineResult {
private static final String GOOGLE_PLAY_LOCATION_RESULT = "com.google.android.gms.location.LocationResult";
private final List<Location> locations;
private LocationEngineResult(List<Location> locations) {
@@ -95,16 +89,7 @@ public final class LocationEngineResult {
*/
@Nullable
public static LocationEngineResult extractResult(Intent intent) {
LocationEngineResult result = null;
if (isOnClasspath(GOOGLE_PLAY_LOCATION_RESULT)) {
result = extractGooglePlayResult(intent);
}
return result == null ? extractAndroidResult(intent) : result;
}
private static LocationEngineResult extractGooglePlayResult(Intent intent) {
LocationResult result = LocationResult.extractResult(intent);
return result != null ? LocationEngineResult.create(result.getLocations()) : null;
return extractAndroidResult(intent);
}
private static LocationEngineResult extractAndroidResult(Intent intent) {

View File

@@ -1,11 +1,8 @@
package com.mapbox.mapboxsdk.location
import android.content.Context
import android.content.res.Resources
import android.content.res.TypedArray
import android.location.Location
import android.os.Looper
import com.mapbox.mapboxsdk.R
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.location.LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS
import com.mapbox.mapboxsdk.location.engine.LocationEngine
@@ -69,60 +66,45 @@ class LocationComponentTest {
@Mock
private lateinit var staleStateManager: StaleStateManager
@Mock
private lateinit var locationEngineProvider: LocationComponent.InternalLocationEngineProvider
@Mock
private lateinit var style: Style
private lateinit var developerAnimationListeners: List<MapboxMap.OnDeveloperAnimationListener>
private val defaultOptions: LocationComponentActivationOptions
get() = LocationComponentActivationOptions.builder(context, style).locationEngine(locationEngine).locationEngineRequest(locationEngineRequest).locationComponentOptions(locationComponentOptions).build()
@Before
fun before() {
MockitoAnnotations.initMocks(this)
developerAnimationListeners = mutableListOf()
locationComponent = LocationComponent(mapboxMap, transform, developerAnimationListeners, currentListener, lastListener, locationLayerController, locationCameraController, locationAnimatorCoordinator, staleStateManager, compassEngine, locationEngineProvider, false)
doReturn(locationEngine).`when`(locationEngineProvider).getBestLocationEngine(context, false)
locationComponent = LocationComponent(mapboxMap, transform, developerAnimationListeners, currentListener, lastListener, locationLayerController, locationCameraController, locationAnimatorCoordinator, staleStateManager, compassEngine, false)
doReturn(style).`when`(mapboxMap).style
}
@Test
fun activateWithRequestTest() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
Assert.assertEquals(locationEngineRequest, locationComponent.locationEngineRequest)
doReturn(mock(TypedArray::class.java)).`when`(context)
.obtainStyledAttributes(R.style.maplibre_LocationComponent, R.styleable.maplibre_LocationComponent)
val resources = mock(Resources::class.java)
doReturn(resources).`when`(context).resources
doReturn(0f).`when`(resources)
.getDimension(R.dimen.maplibre_locationComponentTrackingMultiFingerMoveThreshold)
doReturn(0f).`when`(resources)
.getDimension(R.dimen.maplibre_locationComponentTrackingMultiFingerMoveThreshold)
locationComponent.activateLocationComponent(context, mock(Style::class.java), true, locationEngineRequest)
Assert.assertEquals(locationEngineRequest, locationComponent.locationEngineRequest)
`when`(style.isFullyLoaded).thenReturn(true)
}
@Test
fun activateWithDefaultLocationEngineRequestAndOptionsTestDefaultLocationEngine() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), true, locationEngineRequest, locationComponentOptions)
val options = LocationComponentActivationOptions.builder(context, style).locationEngine(locationEngine).locationEngineRequest(locationEngineRequest).locationComponentOptions(locationComponentOptions).build()
locationComponent.activateLocationComponent(options)
Assert.assertEquals(locationEngineRequest, locationComponent.locationEngineRequest)
Assert.assertNotNull(locationComponent.locationEngine)
}
@Test
fun activateWithDefaultLocationEngineRequestAndOptionsTestCustomLocationEngine() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), false, locationEngineRequest, locationComponentOptions)
val options = LocationComponentActivationOptions.builder(context, style).useDefaultLocationEngine(false).locationEngineRequest(locationEngineRequest).locationComponentOptions(locationComponentOptions).build()
locationComponent.activateLocationComponent(options)
Assert.assertEquals(locationEngineRequest, locationComponent.locationEngineRequest)
Assert.assertNull(locationComponent.locationEngine)
}
@Test
fun locationUpdatesWhenEnabledDisableTest() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
verify(locationEngine, times(0)).removeLocationUpdates(currentListener)
verify(locationEngine, times(0)).requestLocationUpdates(eq(locationEngineRequest), eq(currentListener), any(Looper::class.java))
@@ -140,7 +122,8 @@ class LocationComponentTest {
@Test
fun locationUpdatesWhenStartedStoppedTest() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
@@ -153,7 +136,7 @@ class LocationComponentTest {
@Test
fun locationUpdatesWhenNewRequestTest() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
@@ -165,7 +148,7 @@ class LocationComponentTest {
@Test
fun lastLocationUpdateOnStartTest() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
@@ -174,7 +157,7 @@ class LocationComponentTest {
@Test
fun transitionCallbackFinishedTest() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -192,7 +175,7 @@ class LocationComponentTest {
@Test
fun transitionCallbackCanceledTest() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -210,7 +193,8 @@ class LocationComponentTest {
@Test
fun transitionCustomFinishedTest() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -228,7 +212,7 @@ class LocationComponentTest {
@Test
fun compass_listenWhenConsumedByNoneCamera() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -240,7 +224,7 @@ class LocationComponentTest {
@Test
fun compass_listenWhenConsumedByTrackingCamera() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -252,7 +236,7 @@ class LocationComponentTest {
@Test
fun compass_listenWhenConsumedByLayer() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -264,7 +248,7 @@ class LocationComponentTest {
@Test
fun compass_notListenWhenNotConsumed() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -283,7 +267,7 @@ class LocationComponentTest {
@Test
fun compass_removeListenerOnChange() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -297,7 +281,7 @@ class LocationComponentTest {
@Test
fun compass_removeListenerOnStop() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -310,7 +294,7 @@ class LocationComponentTest {
@Test
fun compass_reAddListenerOnStart() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -324,7 +308,7 @@ class LocationComponentTest {
@Test
fun compass_removeListenerOnStyleStartLoad() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -337,7 +321,7 @@ class LocationComponentTest {
@Test
fun compass_reAddListenerOnStyleLoadFinished() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -351,7 +335,7 @@ class LocationComponentTest {
@Test
fun compass_reAddListenerOnlyWhenEnabled() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -367,7 +351,7 @@ class LocationComponentTest {
@Test
fun compass_notAdListenerWhenDisabled() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -378,7 +362,7 @@ class LocationComponentTest {
@Test
fun compass_notAdListenerWhenStopped() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -389,7 +373,7 @@ class LocationComponentTest {
@Test
fun compass_notAddListenerWhenLayerNotReady() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.onStart()
locationComponent.isLocationComponentEnabled = true
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
@@ -406,7 +390,7 @@ class LocationComponentTest {
@Test
fun developerAnimationCalled() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
for (listener in developerAnimationListeners) {
listener.onDeveloperAnimationStarted()
@@ -416,7 +400,7 @@ class LocationComponentTest {
@Test
fun internal_cameraTrackingChangedListener_onCameraTrackingDismissed() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
val cameraChangeListener: OnCameraTrackingChangedListener = mock(OnCameraTrackingChangedListener::class.java)
@@ -429,7 +413,7 @@ class LocationComponentTest {
@Test
fun internal_cameraTrackingChangedListener_onCameraTrackingChanged() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
val cameraValueListener: AnimatorListenerHolder = mock(AnimatorListenerHolder::class.java)
@@ -451,7 +435,7 @@ class LocationComponentTest {
@Test
fun internal_renderModeChangedListener_onRenderModeChanged() {
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
val cameraListener: AnimatorListenerHolder = mock(AnimatorListenerHolder::class.java)
@@ -476,7 +460,6 @@ class LocationComponentTest {
val projection: Projection = mock(Projection::class.java)
`when`(projection.getMetersPerPixelAtLatitude(location.latitude)).thenReturn(10.0)
`when`(mapboxMap.projection).thenReturn(projection)
`when`(style.isFullyLoaded).thenReturn(true)
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
locationComponent.activateLocationComponent(
@@ -500,7 +483,7 @@ class LocationComponentTest {
@Test
fun tiltWhileTracking_notReady() {
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
val callback = mock(MapboxMap.CancelableCallback::class.java)
@@ -514,7 +497,7 @@ class LocationComponentTest {
fun tiltWhileTracking_notTracking() {
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
`when`(locationCameraController.cameraMode).thenReturn(CameraMode.NONE)
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
locationComponent.onStart()
@@ -530,7 +513,7 @@ class LocationComponentTest {
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
`when`(locationCameraController.cameraMode).thenReturn(CameraMode.TRACKING)
`when`(locationCameraController.isTransitioning).thenReturn(true)
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
locationComponent.onStart()
@@ -546,7 +529,7 @@ class LocationComponentTest {
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
`when`(locationCameraController.cameraMode).thenReturn(CameraMode.TRACKING)
`when`(locationCameraController.isTransitioning).thenReturn(false)
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
locationComponent.onStart()
@@ -560,7 +543,7 @@ class LocationComponentTest {
@Test
fun zoomWhileTracking_notReady() {
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
val callback = mock(MapboxMap.CancelableCallback::class.java)
@@ -574,7 +557,7 @@ class LocationComponentTest {
fun zoomWhileTracking_notTracking() {
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
`when`(locationCameraController.cameraMode).thenReturn(CameraMode.NONE)
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
locationComponent.onStart()
@@ -590,7 +573,7 @@ class LocationComponentTest {
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
`when`(locationCameraController.cameraMode).thenReturn(CameraMode.TRACKING)
`when`(locationCameraController.isTransitioning).thenReturn(true)
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
locationComponent.onStart()
@@ -606,7 +589,7 @@ class LocationComponentTest {
`when`(mapboxMap.cameraPosition).thenReturn(CameraPosition.DEFAULT)
`when`(locationCameraController.cameraMode).thenReturn(CameraMode.TRACKING)
`when`(locationCameraController.isTransitioning).thenReturn(false)
locationComponent.activateLocationComponent(context, mock(Style::class.java), locationEngine, locationEngineRequest, locationComponentOptions)
locationComponent.activateLocationComponent(defaultOptions)
locationComponent.isLocationComponentEnabled = true
locationComponent.onStart()
@@ -624,7 +607,6 @@ class LocationComponentTest {
val projection: Projection = mock(Projection::class.java)
`when`(projection.getMetersPerPixelAtLatitude(location.latitude)).thenReturn(10.0)
`when`(mapboxMap.projection).thenReturn(projection)
`when`(style.isFullyLoaded).thenReturn(true)
locationComponent.activateLocationComponent(
LocationComponentActivationOptions.builder(context, style)
.locationComponentOptions(locationComponentOptions)
@@ -643,8 +625,7 @@ class LocationComponentTest {
fun newLocation_accuracy_indicatorLayerRadiusValue() {
val location = Location("test")
location.accuracy = 50f
`when`(style.isFullyLoaded).thenReturn(true)
locationComponent = LocationComponent(mapboxMap, transform, developerAnimationListeners, currentListener, lastListener, locationLayerController, locationCameraController, locationAnimatorCoordinator, staleStateManager, compassEngine, locationEngineProvider, true)
locationComponent = LocationComponent(mapboxMap, transform, developerAnimationListeners, currentListener, lastListener, locationLayerController, locationCameraController, locationAnimatorCoordinator, staleStateManager, compassEngine, true)
locationComponent.activateLocationComponent(
LocationComponentActivationOptions.builder(context, style)
.locationComponentOptions(locationComponentOptions)

View File

@@ -1,129 +0,0 @@
package com.mapbox.mapboxsdk.location.engine;
import android.location.Location;
import android.os.Looper;
import androidx.annotation.NonNull;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class GoogleLocationEngineImplAdditionalTest {
private static final long INTERVAL = 1000L;
private LocationEngineProxy engine;
private Location location;
private List<Location> locationList = new ArrayList<>();
private FusedLocationProviderClient fusedLocationProviderClient;
private Task<Void> mockTask;
private Task<Location> mockLocationTask;
@Before
public void setUp() {
location = mock(Location.class);
when(location.getLatitude()).thenReturn(1.0);
when(location.getLongitude()).thenReturn(2.0);
locationList.clear();
locationList.add(location);
fusedLocationProviderClient = mock(FusedLocationProviderClient.class);
mockTask = mock(Task.class);
mockLocationTask = mock(Task.class);
when(fusedLocationProviderClient.getLastLocation()).thenReturn(mockLocationTask);
when(fusedLocationProviderClient
.requestLocationUpdates(any(LocationRequest.class), any(LocationCallback.class), any(Looper.class)))
.thenAnswer(new Answer<Task<Void>>() {
@Override
public Task<Void> answer(InvocationOnMock invocation) {
LocationCallback listener = (LocationCallback) invocation.getArguments()[1];
listener.onLocationResult(LocationResult.create(locationList));
return mockTask;
}
});
engine = new LocationEngineProxy<>(new GoogleLocationEngineImpl(fusedLocationProviderClient));
}
@Test
public void checkGetLastLocation() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
when(mockLocationTask.addOnSuccessListener(any(OnSuccessListener.class)))
.thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
OnSuccessListener listener = (OnSuccessListener) invocation.getArguments()[0];
listener.onSuccess(location);
return mock(Task.class);
}
});
engine.getLastLocation(new LocationEngineCallback<LocationEngineResult>() {
@Override
public void onSuccess(LocationEngineResult result) {
List<Location> list = result.getLocations();
assertEquals(1, list.size());
assertEquals(1.0, list.get(0).getLatitude(), 0);
assertEquals(2.0, list.get(0).getLongitude(), 0);
latch.countDown();
}
@Override
public void onFailure(@NonNull Exception exception) {
}
});
assertTrue(latch.await(1, TimeUnit.SECONDS));
}
@Test
public void checkRequestAndRemoveLocationUpdates() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
LocationEngineCallback<LocationEngineResult> engineCallback = new LocationEngineCallback<LocationEngineResult>() {
@Override
public void onSuccess(LocationEngineResult result) {
List<Location> list = result.getLocations();
assertEquals(1, list.size());
assertEquals(1.0, list.get(0).getLatitude(), 0);
assertEquals(2.0, list.get(0).getLongitude(), 0);
latch.countDown();
}
@Override
public void onFailure(@NonNull Exception exception) {
}
};
engine.requestLocationUpdates(getRequest(INTERVAL, LocationEngineRequest.PRIORITY_HIGH_ACCURACY),
engineCallback, mock(Looper.class));
assertTrue(latch.await(1, TimeUnit.SECONDS));
assertNotNull(engine.removeListener(engineCallback));
}
private static LocationEngineRequest getRequest(long interval, int priority) {
return new LocationEngineRequest.Builder(interval).setPriority(priority).build();
}
}

View File

@@ -1,66 +0,0 @@
package com.mapbox.mapboxsdk.location.engine;
import android.app.PendingIntent;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class GoogleLocationEngineImplTest {
@Mock
private FusedLocationProviderClient fusedLocationProviderClientMock;
private LocationEngine engine;
private GoogleLocationEngineImpl googleLocationEngineImpl;
@Before
public void setUp() {
googleLocationEngineImpl = new GoogleLocationEngineImpl(fusedLocationProviderClientMock);
engine = new LocationEngineProxy<>(googleLocationEngineImpl);
}
@Test
public void removeLocationUpdatesForInvalidListener() {
LocationEngineCallback<LocationEngineResult> callback = mock(LocationEngineCallback.class);
engine.removeLocationUpdates(callback);
verify(fusedLocationProviderClientMock, never()).removeLocationUpdates(any(LocationCallback.class));
}
@Test
public void removeLocationUpdatesForPendingIntent() {
PendingIntent pendingIntent = mock(PendingIntent.class);
engine.removeLocationUpdates(pendingIntent);
verify(fusedLocationProviderClientMock, times(1))
.removeLocationUpdates(any(PendingIntent.class));
}
@Test(expected = NullPointerException.class)
public void getLastLocationNullCallback() {
engine.getLastLocation(null);
}
@Test(expected = NullPointerException.class)
public void requestLocationUpdatesNullCallback() {
engine.requestLocationUpdates(null, null, null);
}
@After
public void tearDown() {
reset(fusedLocationProviderClientMock);
engine = null;
}
}

View File

@@ -1,14 +0,0 @@
package com.mapbox.mapboxsdk.location.engine;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class LocationEngineProviderTest {
@Test(expected = NullPointerException.class)
public void passNullContext() {
LocationEngineProvider.getBestLocationEngine(null, false);
}
}

View File

@@ -74,7 +74,6 @@ dependencies {
implementation dependenciesList.multidex
implementation dependenciesList.gmsLocation
implementation dependenciesList.timber
implementation dependenciesList.okhttp3

View File

@@ -71,4 +71,4 @@ class StyleLoaderTest : EspressoTest() {
}
}
}
}
}

View File

@@ -28,4 +28,4 @@ class FontUtilsTest {
val actual = FontUtils.extractValidFont(null)
Assert.assertNull(actual)
}
}
}

View File

@@ -10,7 +10,7 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.location.LocationComponent
import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions
import com.mapbox.mapboxsdk.location.engine.LocationEngine
import com.mapbox.mapboxsdk.location.engine.LocationEngineProvider
import com.mapbox.mapboxsdk.location.engine.LocationEngineDefault
import com.mapbox.mapboxsdk.location.engine.LocationEngineRequest
import com.mapbox.mapboxsdk.location.modes.RenderMode
import com.mapbox.mapboxsdk.location.permissions.PermissionsListener
@@ -29,7 +29,7 @@ class ManualLocationUpdatesActivity : AppCompatActivity(), OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_location_manual_update)
locationEngine = LocationEngineProvider.getBestLocationEngine(this, false)
locationEngine = LocationEngineDefault.getDefaultLocationEngine(mapView.context)
val fabManualUpdate = findViewById<FloatingActionButton>(R.id.fabManualLocationChange)
fabManualUpdate.setOnClickListener { v: View? ->
if (locationComponent != null && locationComponent!!.locationEngine == null) {

View File

@@ -37,7 +37,6 @@ ext {
kotlin : '1.7.20',
licenses : '0.8.80',
lint : '30.3.1',
gms : '21.0.1',
// jacoco : '0.8.5',
appcenter : '1.5',
commonsIO : '2.11.0',
@@ -75,7 +74,6 @@ ext {
appCenter : "com.microsoft.appcenter:espresso-test-extension:${versions.appcenter}",
commonsIO : "commons-io:commons-io:${versions.commonsIO}",
gmsLocation : "com.google.android.gms:play-services-location:${versions.gms}",
timber : "com.jakewharton.timber:timber:${versions.timber}",
okhttp3 : "com.squareup.okhttp3:okhttp:${versions.okhttp}",
leakCanary : "com.squareup.leakcanary:leakcanary-android:${versions.leakCanary}",